【问题标题】:Binding in Xamarin.Forms does not work after web API requestWeb API 请求后 Xamarin.Forms 中的绑定不起作用
【发布时间】:2019-03-05 18:19:30
【问题描述】:

我正在尝试制作简单的应用程序,该应用程序将提供通过 Web API 向数据库读取/写入数据的功能。 我有绑定到视图的视图模型,但在 web api 获取请求后它无法正常工作,即使该调用已成功完成。我尝试使用显示警报检查值,值是正确的,但它没有显示在视图部分,而是显示在一个标签中。这是我的代码:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         x:Class="SOSEUApp.Pages.NotePage"
         Title="Dnevnik">
<ContentPage.ToolbarItems>
    <ToolbarItem Text="GET" Clicked="ToolbarItem_Clicked"></ToolbarItem>
</ContentPage.ToolbarItems>
<ContentPage.Content>
    <StackLayout Orientation="Vertical">
        <ActivityIndicator IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}"></ActivityIndicator>
        <StackLayout Orientation="Vertical">
            <Label Text="{Binding Date,StringFormat='Date: {0}'}"></Label>
        </StackLayout>
        <StackLayout>

        </StackLayout>
    </StackLayout>
</ContentPage.Content>

 [XamlCompilation(XamlCompilationOptions.Compile)]
public partial class NotePage : ContentPage
{
    NoteViewModel nvm = new NoteViewModel();
    public NotePage()
    {
        InitializeComponent();
        BindingContext = nvm;
    }

    private async void ToolbarItem_Clicked(object sender, EventArgs e)
    {
        nvm.IsBusy = true;
        nvm.Notes = await App.NotesWebApiService.GetAll(nvm.CurrentActiveNote.Route);
        nvm.GetLastNote();
        nvm.IsBusy = false;
        await DisplayAlert("Info", nvm.Date.ToString(), "Close");
    }
}

公共类 NoteViewModel : BaseViewModel {

    IList<Note> notes = new List<Note>();
    public IList<Note> Notes
    {
        get { return notes; }
        set { SetProperty(ref notes, value); }
    }

    private Note currentActiveNote = new Note();
    public Note CurrentActiveNote { get { return currentActiveNote; } }

    public string Date { get { return currentActiveNote.Date.ToString("dd.MM.yyyy"); } }
    public string OrderedNumber
    {
        get { return currentActiveNote.OrderNumber.ToString(); }
        set
        {
            string v = currentActiveNote.OrderNumber.ToString();
            SetProperty(ref v, value);
            currentActiveNote.OrderNumber = Convert.ToInt16(v);
        }
    }


    public string Description
    {
        get { return currentActiveNote.Description; }
        set
        {
            string v = currentActiveNote.Description;
            SetProperty(ref v, value);
            currentActiveNote.Description = v;
        }
    }


    public void GetLastNote()
    {

        notes.OrderBy(a => a.Date);
        currentActiveNote = notes.Last();
    }

}

公共类 BaseViewModel : DataModel, INotifyPropertyChanged {

    bool isBusy = false;
    public bool IsBusy
    {
        get { return isBusy; }
        set { SetProperty(ref isBusy, value); }
    }

    string title = string.Empty;
    public string Title
    {
        get { return title; }
        set { SetProperty(ref title, value); }
    }

    protected bool SetProperty<T>(ref T backingStore, T value,
        [CallerMemberName]string propertyName = "",
        Action onChanged = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value))
            return false;

        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var changed = PropertyChanged;
        if (changed == null)
            return;

        changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

提前谢谢你!

【问题讨论】:

  • 明确命名属性会有所帮助;-)
  • 您绑定的唯一属性是 Date,并且您的 VM 在更新时不会为 Date 触发任何 PropertyChanged 事件
  • 可以通过哪些方式更改?
  • 您需要在 Date 更改时触发 PropertyChanged 事件 - 这可能会在 currentactivenote 更改时发生,但您需要弄清楚
  • 你有没有试过PropertyChanged解决这个问题?如果有其他问题,你可以显示。

标签: asp.net-web-api mvvm data-binding xamarin.forms


【解决方案1】:

刚刚调用了 SetProperty 方法并在那里传递了所需的值。有效

如 Jason 所说,您需要在 Date 更改时触发 PropertyChanged 事件。这里是 official document 供参考。

一般情况下,通常写在Set方法中。如下:

 private string propertyname;

 public string PropertyName
    {
        set { SetProperty(ref propertyname, value); }
        get { return propertyname; }
    }

或者写成如下:

 public string PropertyName
        {
            set
            {
                if (propertyname!= value)
                {
                    propertyname= value;
                    OnPropertyChanged("PropertyName");
                }
            }
            get
            {
                return propertyname;
            }
        }

bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
    if (Object.Equals(storage, value))
        return false;

    storage = value;
    OnPropertyChanged(propertyName);
    return true;
}

protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

当模型数据发生变化时,会自动调用。

【讨论】:

    猜你喜欢
    • 2017-11-02
    • 2014-03-14
    • 1970-01-01
    • 2018-12-09
    • 2019-04-29
    • 2019-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多