gpt4 book ai didi

c# - Xamarin.Forms:IValueConverter 只工作一次

转载 作者:行者123 更新时间:2023-12-03 10:32:57 25 4
gpt4 key购买 nike

我试图通过更改所选标签的颜色来控制标签的背景颜色。我遵循 MVVM 模式,我实现的方式如下:

  • 在模型中,我创建了一个带有 get 和 set 的 bool 值,它必须检测是否选择了我的 ListView 中的项目。 public boolean Selected {get; set;}
  • 在我看来,我将背景颜色属性绑定(bind)到 bool 值,并将 IValueConverter 设置为 Converter
  • 在 ViewModel 中,我实现了 get 和 set

  • 似乎它只检查一次,因为背景颜色总是白色的。我已经用转换器中的断点检查了它,它只在列表启动时被调用,而不是在项目更新时被调用。

    值转换器:
    public class SelectedItemColorConverter : IValueConverter
    {

    #region IValueConverter implementation

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
    if (value is bool)
    {
    if ((Boolean)value)
    return Color.Red;
    else
    return Color.White;
    }
    return Color.White;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
    throw new NotImplementedException();
    }

    #endregion
    }
    }

    这是 ListView :
    <StackLayout x:Name="standingsStackLayout" IsVisible="False">
    <ListView x:Name="standingsList" SeparatorColor="Black" ItemsSource="{Binding StandingsListSource}" SelectedItem="{Binding SelectedItem}">
    <ListView.ItemTemplate>
    <DataTemplate>
    <ViewCell>
    <Label x:Name="TournamentNameLabel" Text="{Binding TournamentName}"
    TextColor="{StaticResource textColor}" HorizontalTextAlignment="Center"
    VerticalTextAlignment="Center"
    BackgroundColor="{Binding Selected, Converter={StaticResource colorConvert}}"/>
    </ViewCell>
    </DataTemplate>
    </ListView.ItemTemplate>
    </ListView>
    </StackLayout>

    View 模型代码:
    public HistoricalStandingsData _selectedItem;
    public HistoricalStandingsData SelectedItem
    {
    get { return _selectedItem; }
    set
    {
    if (_selectedItem != value)
    {
    if(_selectedItem != null)
    _selectedItem.Selected = false;

    _selectedItem = value;

    if (_selectedItem != null)
    _selectedItem.Selected = true;


    TournamentLabelName = _selectedItem.TournamentName;

    OnPropertyChanged(nameof(SelectedItem));
    //OnPropertyChanged(nameof(_selectedItem.Selected));
    }
    }
    }

    我添加了 <ContentPage.Resources>对于转换器

    最佳答案

    让我们看看你的观点

    <StackLayout x:Name="standingsStackLayout" IsVisible="False">
    <ListView x:Name="standingsList" SeparatorColor="Black" ItemsSource="{Binding StandingsListSource}" SelectedItem="{Binding SelectedItem}">
    <ListView.ItemTemplate>
    <DataTemplate>
    <ViewCell>
    <Label x:Name="TournamentNameLabel" Text="{Binding TournamentName}"
    TextColor="{StaticResource textColor}" HorizontalTextAlignment="Center"
    VerticalTextAlignment="Center"
    BackgroundColor="{Binding Selected, Converter={StaticResource colorConvert}}"/>
    </ViewCell>
    </DataTemplate>
    </ListView.ItemTemplate>
    </ListView>
    </StackLayout>

    我们可以看到这里发生了两个主要的数据绑定(bind)。一、 ListViewItemsSource属性绑定(bind)到 StandingsListSource您的 View 模型的属性。有两件事可以改变这一点: StandingsListSource 指向的对象。作为一个整体或集合内容。

    绑定(bind)的官方文档有 following to say regarding binding ListView.ItemsSource :

    The ListView is quite sophisticated in handling changes that might dynamically occur in the underlying data, but only if take certain steps. If the collection of items assigned to the ItemsSource property of the ListView changes during runtime—that is, if items can be added to or removed from the collection—use an ObservableCollection class for these items. ObservableCollection implements the INotifyCollectionChanged interface, and ListView will install a handler for the CollectionChanged event.



    让我们这样做( DataSource 类的完整实现,我将其用作 BindingContext 用于稍后的表单):
    public ObservableCollection<HistoricalStandingsData> StandingsListSource { get; } = new ObservableCollection<HistoricalStandingsData>();

    为简单起见,我制作了 StandingsListSource一个 C# 6.0 readonly auto property以消除跟踪其重新分配的需要。

    现在,自从 ListView.SelectedItem也被绑定(bind)了,我们需要某种方式来通知 ListView该选定项目是从后面的代码更新的。输入前面提到的文档中的第二条建议:

    If properties of the items themselves change during runtime, then the items in the collection should implement the INotifyPropertyChanged interface and signal changes to property values using the PropertyChanged event.



    这有两个含义:
  • HistoricalStandingsData应该在其属性更改时通知,因为 ListView 中的每一行根据 DataTemplate 绑定(bind)到此属性:
    public class HistoricalStandingsData : INotifyPropertyChanged
    {
    public HistoricalStandingsData(string name)
    {
    this.TournamentName = name;
    }

    private bool selected;

    public bool Selected
    {
    get
    {
    return selected;
    }

    set
    {
    selected = value;
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Selected)));
    }
    }

    public string TournamentName { get; }

    // From INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    }
  • View 模型类应该实现 INotifyPropertyChanged通知属性,在本例中为 SelectedItem变化。
    class DataSource : INotifyPropertyChanged
    {
    public ObservableCollection<HistoricalStandingsData> Items { get; } = new ObservableCollection<HistoricalStandingsData>();

    public HistoricalStandingsData SelectedItem
    {
    // Information on selection is stored in items themselves, use Linq to find the single matching item
    get => Items.Where(x => x.Selected).SingleOrDefault();
    set
    {
    // Reset previous selection
    var item = SelectedItem;
    if (item != null)
    item.Selected = false;

    // Mark new item as selected, raising HistoricalStandingItem.PropertyChanged
    if (value != null)
    value.Selected = true;

    // Notify observers that SelectedItem changed
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItem)));
    }
    }

    // From INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;

    public DataSource()
    {
    // Helper ICommand used for appending new items to HistoricalStandingsData
    AddNew = new Command(() =>
    {
    var item2 = new HistoricalStandingsData(DateTime.Now.ToString());
    // Append, notifies observers that collection has changed.
    Items.Add(item2);
    // Set as selected, resetting previous selection
    SelectedItem = item2;
    });
    }

    public ICommand AddNew { get; }
    }
  • AddNew命令是可选的,我添加它是为了测试目的。

    关于c# - Xamarin.Forms:IValueConverter 只工作一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48229628/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com