我有一个ObservableCollection,我需要绑定到2个标签,首先显示集合中的项目数,然后显示值的总和。
第一个标签绑定到集合计数属性,第二个标签直接绑定到ObservableCollection,带有转换器以计算所有项目的总和
XAML看起来像这样
<Grid>
<ListBox Name="itemList" ItemsSource="{Binding DataList}"/>
<Label Name="lblcount" Content="{Binding DataList.Count}" />
<Label Name="lblTotal" Content="{Binding DataList, Converter={StaticResource calculateTotalConvertor}" />
</Grid>
我的VM有一个像这样的集合
ObservableCollection<int> data = new ObservableCollection<int>();
public ObservableCollection<int> DataList
{
get { return data; }
set { data = value; }
}
我的转换器代码是
public class CalculateTotalConvertor : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
ObservableCollection<int> collection = value as ObservableCollection<int>;
return collection.Sum();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
问题是在DataList,ListView和标签中添加新项目,显示项目的计数得到更新,但“lblTotal”没有更新总计数。
基本上如何强制在ObservableCollection更改时评估绑定?它如何直接用于ListView或DataGrid而不用于标签?
我知道这个问题可以通过在VM中创建一个属性来解决,以便在集合更新时显示总数并提高属性更改但是有没有比这更好的解决方案?
当然这是我实际问题的简化形式,我没有访问ViewModel和集合,它是第三方控件。我正在创建一个包装器用户控件,并且具有与其内部集合的视图的相对绑定。
答案 0 :(得分:3)
其他答案正确解释了为什么它没有更新。要强制更新,您可以将转换器更改为IMultiValueConverter
:
public class CalculateTotalConvertor : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
ObservableCollection<int> collection = values.FirstOrDefault() as ObservableCollection<int>;
return collection.Sum();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
然后将你的绑定更改为MultiBinding
,同时拉入计数:
<Label Name="lblTotal">
<Label.Content>
<MultiBinding Converter="{StaticResource calculateTotalConvertor}">
<Binding Path="DataList"/>
<Binding Path="DataList.Count"/>
</MultiBinding>
</Label.Content>
</Label>
现在第二个绑定将通知绑定需要在添加或删除项目时更新,但您可以忽略计数值而不使用它。
答案 1 :(得分:0)
它没有更新,因为它绑定到DataList
和DataList
没有改变,计数标签更新,因为它绑定到DataList.Count
,当项目添加到列表时更新。{1}}。
我能想到更新Sum
标签的唯一方法是通知UI DataList
已更改,但这会导致ListBox重新绑定列表,它将是性能将是比模型上的属性更新Sum
更贵。
所以我认为最好的选择是使用模型上的属性来计算使用ObservableCollections
CollectionChangedEvent
或在将项添加到列表的逻辑中的总和
答案 2 :(得分:0)
适用于ListView
和DataGrid
,因为它们是ItemsControl
,可以收听ObservableCollection
的{{1}},这是在收集时引发的通过添加或删除项目来改变本身。
另一方面,CollectionChangedEvent
只是Label
,只会收听ContentControl
。由于您的DataList在插入之后与之前的PropertyChangedEvent
相同,因此不会引发任何事件。
刚看到你的编辑:
如果要创建包装控件,请为第三方控件指定一个名称,并从控件的代码后面连接其内部集合ObservableCollection
。这样,您仍然可以将更新通知推送到包装视图。
使用额外属性,它将为转换器节省一些代码。从背后的代码:
CollectionChangedEvent