【问题标题】:MVVM update listbox item backcolor using button command [duplicate]MVVM使用按钮命令更新列表框项目背景色[重复]
【发布时间】:2017-11-12 09:41:44
【问题描述】:

我正在尝试使用以下命令独立更新列表框项目背景: 型号

public class Item
{
    public Item()
    {
        this.BackColor = new SolidColorBrush(Colors.WhiteSmoke);
    }

    public int Number { get; set; }
    public int Duration { get; set; }
    public string Name { get { return Number.ToString(); } }
    public SolidColorBrush BackColor { get; set; }
}

视图模型

private ObservableCollection<Item> _items;

public ObservableCollection<Item> Items
{
    get { return _items; }
    set { OnPropertyChange(ref _items, value); }
}

按钮命令

public ICommand StartCommand { get; set; }

public void start()
{
    foreach (var item in Items
    {
        item.BackColor = new SolidColorBrush(Colors.LightGreen);
        // Do some work .....
    }
}

导演

public MainViewModel()
{
    StartCommand = new RelayCommand(start);
    LoadItems();
}

Xaml

<ListBox  ItemsSource="{Binding Items}" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Border 
                Height="50" 
                BorderThickness="1" 
                BorderBrush="Silver" 
                CornerRadius="5" 
                Margin="10,10,10,5" 
                Background="{Binding BackColor,
                UpdateSourceTrigger=PropertyChanged}">
            </Border>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我可以更新可观察的集合数据,删除项目但不能更改项目背景。请帮助。

"Update" :如您所见,我不想更改整个列表框的颜色,所以我不能绑定到像“ItemBackground”这样的公共属性,而是必须绑定到集合对象属性“BackColor” "

【问题讨论】:

  • 我觉得不一样。因为我不想更改整个项目列表的背景颜色。我需要单独更改每个项目的颜色
  • 你需要在你的Item类中实现INotifyPropertyChanged
  • @Fruchtzwerg 是对的,您只是缺少INotifyPropertyChanged 实现。但是,由于您使用的是 mvvm,因此您应该重新考虑将背景保存为模型中的 Brush。在 mvvm 中,模型应该对视图一无所知,Brush 是视图的一部分。考虑改为保存一些状态,并使用转换器将其更改为背景。
  • @CKII 在视图模型中使用像 Brush 这样的框架类型是否违反 MVVM 是这里反复讨论的问题。当然,使用类型 Brush 并不意味着您所说的“视图模型知道视图”。但是,它可以避免重复使用使用不同画笔类型的视图。但这当然不太可能发生。 IMO,使用任何不是从 UIElement 派生的类型都是完全有效的视图模型类型,如 Color、Brush、Pen、Geometry、ImageSource 等。
  • @EmadAli 注意,在后台绑定上设置UpdateSourceTrigger=PropertyChanged 是没有意义的。它仅在 TwoWay 或 OneWayToSource 绑定中有效。另请注意,您也可以写Brushes.LightGreen,而不是new SolidColorBrush(Colors.LightGreen)

标签: c# wpf mvvm


【解决方案1】:

就像@pix 在链接帖子中所建议的那样,您在项目类中缺少INotifyPropertyChanged 接口实现。如果没有 INotifyPropertyChanged,您的 UI 将不会获得您所做更改的更新。

public class Item : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

您的BackColor 属性必须使用 OnPropertyChanged:

private SolidColorBrush backColor;

public SolidColorBrush BackColor
{
    get { return backColor; }
    set
    {
        backColor = value;
        OnPropertyChanged(nameof(BackColor));
    }
}

【讨论】:

  • 不使用时为什么要声明CallerMemberName?也就是说,如果您仔细阅读该问题,您会发现 OP 已经有另一个实现 INotifyPropertyChanged 的​​视图模型。似乎不需要解释它是如何实现的。
  • @Clemens 只是为了更清楚地显示 PropertyChanged 与 BackColor 属性一起使用。确实不需要。
  • 我已经在我的视图模型而不是项目模型上实现了 INotifyPropertyChange。此外,我认为为“backcolor”设置一个属性将影响所有列表框项目,而不是我的 foreach 循环中的当前项目。我说的对吗?
  • 你不对。 BackgroundColor 属性是您的 Item 类的一部分。这意味着您添加到列表中的每个项目都会有自己的颜色。此外,为了让您的 UI 对 Items 类本身的更改做出反应,您必须实现 INotifyPropertyChanged。
猜你喜欢
  • 1970-01-01
  • 2012-10-20
  • 1970-01-01
  • 2012-04-25
  • 2014-08-04
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
相关资源
最近更新 更多