触发集合中某些元素的PropertyChanged

时间:2018-06-23 13:57:03

标签: c# wpf combobox binding inotifypropertychanged

ViewModel中有两个集合,一个集合作为DataGrid行源(在这种情况下,只有值1,2,3,。 )和代表DataGrid中一列的 sequencer 的其他对象(基于ID公开了一些属性值)。

在下面的示例中,我使用了默认的ObservableObjectFullyObservableCollection行为,但也尝试将其用于其他类型的集合,但均未成功。使用DataGridComboBoxColumnDataGridTemplateColumnComboBox上都测试了WPF行为。


ViewModel:

public class ViewModel : ObservableObject
{
    private FullyObservableCollection<Seq> mSequencer;
    public FullyObservableCollection<Seq> Sequencer
    {
        get { return mSequencer; }
        set { SetProperty(ref mSequencer, value); }
    }

    private FullyObservableCollection<RowSrc> mRowSource;
    public FullyObservableCollection<RowSrc> RowSource
    {
        get { return mRowSource; }
        set { SetProperty(ref mRowSource, value); }
    }
}

类定义:

public class Seq : ObservableObject
{
    private int mId;
    public int Id
    {
        get { return mId; }
        set { SetProperty(ref mId, value); }
    }

    private string mName;
    public string Name
    {
        get { return mName; }
        set { SetProperty(ref mName, value); }
    }
}

public class RowSrc : ObservableObject
{
    private int mValue;
    public int Value
    {
        get { return this.mValue; }
        set { SetProperty(ref mValue, value); }
    }
}

查看-XAML:

<CollectionViewSource x:Key="Proxy" Source="{Binding Sequencer}"/>

<DataGrid ItemsSource="{Binding RowSource}">
  <DataGrid.Columns>
    <DataGridComboBoxColumn
                    ItemsSource="{Binding Source={StaticResource Proxy}"
                    SelectedValueBinding="{Binding Value}"
                    SelectedValuePath="Id"
                    DisplayMemberPath="Name"/>
    </DataGridComboBoxColumn>
  </DataGrid.Columns>
</DataGrid>

从上面开始,datagrid已初始化为RowSource的值,该值将通过绑定隧道到达Proxy,该隧道将导致Sequencer。根据每一行的Value,将从Id集合中返回具有相同Sequencer的对象。

照原样,一切都很好。当我们想清空音序器并再次填充时,问题就开始了。

Sequencer.Clear();
Sequencer.AddRange(...);

现在刷新Sequencer中的项目,但是Row[n].Combobox和Sequencer中的项目之间的绑定请勿刷新。其背后的原因是属性本身并未更改,仅更改了集合中的项目。


解决方法-破解:

public class RowSrc
{
    ...

    public void InvokeChange()
    {
        OnPropertyChanged(nameof(Value));
    }
}

public class ViewModel
{
    Sequencer.Clear();
    Sequencer = GenerateNewCollection();

    //after update of Sequencer
    foreach (var nRowSrc in RowSrc) nRowSrc.InvokeChange();
}

但是,这意味着我们需要将此特定方法添加到每个Model类中,然后记住在每次Sequencer更改时都调用它们。

问:如何在集合发生更改时自动调用属性更改,或者如何正确处理此绑定?

2 个答案:

答案 0 :(得分:0)

对于您发布的问题,非常简单,只需使用dt = datetime.now() t1 = [time(00,00), time(06,01), time(12,01), time(18,01)] t2 = [time(06,00), time(12,00), time(18,00), time(23,59)] for quadrant in range(4): if (t1[quadrant] <= dt and dt <= t2[quadrant]): print("The current time is in quadrant: {0}".format(quadrant)) 而不是ObsevrableCollection。实际上,List不仅报告了ObsevrableCollectionAdd,而且还报告了Remove事件所支持的所有运动。因此,如果使用INotifyCollectionChanged.CollectionChanged的索引器设置元素,则将引发ObsevrableCollection类型的CollectionChanged,绑定引擎将对此进行处理。但是读完您的评论后,我有些困惑,无法确定这是否真的是您想要的。

答案 1 :(得分:0)

您可以通过调用Prop1来引发属性MyList[0].OnPropertyChanged(nameof(Foo.Prop1));的PropertyChanged事件。

无需创建TriggerPropertyChanged方法。

之所以可行,是因为在您的示例中,OnPropertyChanged是公用的,并且可以选择接受描述属性名称的字符串。