Xamarin.Forms 如何更改 UI DataTemplate 中的标签文本

Xamarin.Forms How to change UI label text inside DataTemplate

这段代码显示了几行图标和文本,看起来像一个简单的菜单。下面的代码工作正常。但有时我需要更改一个或多个标签的文本。

.xaml

<Frame HorizontalOptions="End" VerticalOptions="Start" BackgroundColor="Black" CornerRadius="5" >       
        <StackLayout Margin="0" Spacing="15" BindableLayout.ItemsSource="{Binding StockItemCollection}">
        <BindableLayout.ItemTemplate>
            <DataTemplate>
                <StackLayout Orientation="Horizontal" Spacing="20">
                    <StackLayout.GestureRecognizers>
                        <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
                    </StackLayout.GestureRecognizers>
                    <Image Source="{Binding StockItemIcon}" WidthRequest="15" HeightRequest="15" BackgroundColor="Transparent"
                        VerticalOptions="Center" HorizontalOptions="Start"/>
                    <Label Text="{Binding StockItemTitle}" TextColor="White" FontSize="16" FontAttributes="Bold" 
                        HorizontalOptions="Start" VerticalOptions="Center"/>
                </StackLayout>
            </DataTemplate>
        </BindableLayout.ItemTemplate>
    </StackLayout>
</Frame>                

背后的代码...

  public MainPage()
  {
      InitializeComponent();
            .
            .
            .

      LoadStock();
      this.BindingContext = this;

  }

  public ObservableCollection<StockItem> StockItemCollection { get; set; }
 
  private void LoadStock()
  {
      StockItemCollection = new ObservableCollection<StockItem>
      {
          new StockItem { StockItemTitle = "ItemTitle 0", StockItemIcon = "Item0.png" },
          new StockItem { StockItemTitle = "ItemTitle 1", StockItemIcon = "Item1.png" },
          new StockItem { StockItemTitle = "ItemTitle 2", StockItemIcon = "Item2.png" },
          new StockItem { StockItemTitle = "ItemTitle 3", StockItemIcon = "Item3.png" },
          new StockItem { StockItemTitle = "ItemTitle 4", StockItemIcon = "Item4.png" },
          new StockItem { StockItemTitle = "ItemTitle 5", StockItemIcon = "Item5.png" }
      };
  }

              
  public class StockItem
  {
      public string StockItemTitle { get; set; }
      public string StockItemIcon { get; set; }
  }

...测试获取和设置...

  Device.BeginInvokeOnMainThread(() =>
  {
        .
        .
        .
        
      string before_StockItem = StockItemCollection[4].StockItemTitle; 
      // before_StockItem = "ItemTitle 4"
      .
      StockItemCollection[4].StockItemTitle = "Item 4 title Edited";
      .
      string after_StockItem = StockItemCollection[4].StockItemTitle; 
      
      // after_StockItem = "Item 4 title Edited"
      // Problem: value updated here but NOT the label in the UI
  });                

这就是问题所在。 UI 中更新的值为 Not updated。 请任何人帮助。谢谢

This is where the problem is. The updated value is Not updated in the UI.

正如 Jason 所说,要在运行时更新视图,请让模型 class 实现 INotifyPropertyChanged 接口以触发 PropertyChanged。检查 tutorial.

试试下面的代码:

public class CustomModel : INotifyPropertyChanged
{
    private string content;
    public string Content
    {
        get
        {
            return content;
        }
        set
        {
            if (content != value)
            {
                content = value;
                NotifyPropertyChanged();
            }
        }
    }
    protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

这是 运行 gif:

我之前尝试过实施 INotifyPropertyChanged ,但做错了导致 PropertyChanged 没有触发。感谢 Jason 让我再次尝试并最终正确完成。

所以我想我应该在这里回答我自己的问题,我希望它也能帮助其他人。

参考:https://docs.microsoft.com/en-us/dotnet/desktop/winforms/how-to-implement-the-inotifypropertychanged-interface?view=netframeworkdesktop-4.8

实施INotifyPropertyChanged通过改变这个

public class StockItem
{
   public string StockItemTitle { get; set; }
   public string StockItemIcon { get; set; }
}

对此...

 public class StockItem : INotifyPropertyChanged
 {
     private string _stockItemTitle = string.Empty;
     public string StockItemIcon { get; set; }

     public event PropertyChangedEventHandler PropertyChanged;

     private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
     {
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
     }

     public string StockItemTitle
     {
         get
         {
             return this._stockItemTitle;
         }

         set
         {
             if (value != this._stockItemTitle)
             {
                 this._stockItemTitle = value;
                 NotifyPropertyChanged();
             }
         }
     }
 }