WPF数据绑定,可观察到要标记的集合
我有一个ObservableCollection,我需要绑定到2个标签,首先显示集合中项目的数量,其次显示值的总和 第一个标签绑定到collections count属性,第二个标签直接绑定到ObservableCollection,使用转换器计算所有项的总数 XAML看起来像这样WPF数据绑定,可观察到要标记的集合,wpf,xaml,data-binding,Wpf,Xaml,Data Binding,我有一个ObservableCollection,我需要绑定到2个标签,首先显示集合中项目的数量,其次显示值的总和 第一个标签绑定到collections count属性,第二个标签直接绑定到ObservableCollection,使用转换器计算所有项的总数 XAML看起来像这样 <Grid> <ListBox Name="itemList" ItemsSource="{Binding DataList}"/> <Label Name="lblco
<Grid>
<ListBox Name="itemList" ItemsSource="{Binding DataList}"/>
<Label Name="lblcount" Content="{Binding DataList.Count}" />
<Label Name="lblTotal" Content="{Binding DataList, Converter={StaticResource calculateTotalConvertor}" />
</Grid>
ObservableCollection<int> data = new ObservableCollection<int>();
public ObservableCollection<int> DataList
{
get { return data; }
set { data = value; }
}
我的虚拟机有这样一个集合
<Grid>
<ListBox Name="itemList" ItemsSource="{Binding DataList}"/>
<Label Name="lblcount" Content="{Binding DataList.Count}" />
<Label Name="lblTotal" Content="{Binding DataList, Converter={StaticResource calculateTotalConvertor}" />
</Grid>
ObservableCollection<int> data = new ObservableCollection<int>();
public ObservableCollection<int> DataList
{
get { return data; }
set { data = value; }
}
ObservableCollection数据=新的ObservableCollection();
公共可观察收集数据列表
{
获取{返回数据;}
设置{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();
}
}
公共类CalculateTotalConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
ObservableCollection集合=作为ObservableCollection的值;
return collection.Sum();
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
抛出新的NotImplementedException();
}
}
问题是在DataList、ListView和显示项目计数的标签中添加新项目时得到更新,但“lblTotal”并没有得到总计数的更新
基本上,如何强制您的绑定根据可观察的收集更改进行评估?它如何直接用于ListView或DataGrid,而不用于label
我知道这个问题可以通过在VM中创建一个属性来解决,在集合更新时显示total并引发属性更改,但有比这更好的解决方案吗
当然,这是我实际问题的简化形式,我没有访问ViewModel和集合的权限,它是第三方控件。我正在创建一个包装器用户控件,并与视图有一个相对绑定到它的内部集合。它没有更新,因为它绑定到
DataList
和DataList
没有更改,计数标签更新,因为它绑定到DataList.count
,当一个项目添加到列表中时更新
我能想到的更新Sum
标签的唯一方法是通知用户界面DataList
已更改,但这将导致列表框重新绑定列表,其性能将比仅在模型上使用属性更新Sum
要昂贵得多
因此,我认为最好的选择是在模型上使用一个属性,使用
可观察集合集合更改开发
或在将项目添加到列表的逻辑中计算总和ListView
和DataGrid
,因为这些是侦听ObservableCollection
的CollectionChangedEvent
的项控件,当通过添加或删除项更改集合本身时,会引发该控件
另一方面,标签是一个ContentControl
,它只侦听属性changedevent
。由于数据列表在插入后与插入前相同,因此不会引发任何事件
刚刚看到您的编辑:
如果要创建包装控件,请为第三方控件指定名称,并从控件的代码隐藏连接到其内部集合的CollectionChangedEvent
。这样,您仍然可以将更新通知推送到包装视图
使用额外的属性,它将在转换器上为您保存一些代码。从代码背后:
public partial class MainWindow : Window, INotifyPropertyChanged
{
ObservableCollection<int> _list = new ObservableCollection<int>();
int _sum = 0;
Random rnd = new Random();
public MainWindow()
{
DataList = new ObservableCollection<int>();
DataList.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(DataList_CollectionChanged);
DataContext = this;
InitializeComponent();
}
void DataList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (object number in e.NewItems)
_sum += (int)number;
break;
case NotifyCollectionChangedAction.Remove:
foreach (object number in e.OldItems)
_sum -= (int)number;
break;
}
OnNotifyPropertyChanged("Sum");
}
public int Sum { get { return _sum; } }
public ObservableCollection<int> DataList { get; set; }
private void Add_Btn_Click(object sender, RoutedEventArgs e)
{
DataList.Add(rnd.Next(0, 256));
}
private void Remove_Btn_Click(object sender, RoutedEventArgs e)
{
if (DataList.Count == 0)
return;
DataList.RemoveAt(DataList.Count - 1);
}
public event PropertyChangedEventHandler PropertyChanged;
void OnNotifyPropertyChanged(string property)
{
if (PropertyChanged == null)
return;
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public分部类主窗口:窗口,INotifyPropertyChanged
{
ObservableCollection_list=新的ObservableCollection();
int _sum=0;
随机rnd=新随机();
公共主窗口()
{
DataList=新的ObservableCollection();
DataList.CollectionChanged+=新系统.Collections.Specialized.NotifyCollectionChangedEventHandler(DataList\u CollectionChanged);
DataContext=this;
初始化组件();
}
无效数据列表\u CollectionChanged(对象发送方,System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
foreach(e.NewItems中的对象编号)
_总和+=(整数)个数;
打破
案例NotifyCollectionChangedAction。删除:
foreach(e.OldItems中的对象编号)
_总和-=(整数)个数;
打破
}
OnNotifyPropertyChanged(“金额”);
}
公共整数和{get{return_Sum;}}
公共ObservableCollection数据列表{get;set;}
私有无效添加\u Btn\u单击(对象发送者,路由目标)
{
DataList.Add(rnd.Next(0256));
}
私有无效删除\u Btn\u单击(对象发送方,路由目标)
{
如果(DataList.Count==0)
返回;
DataList.RemoveAt(DataList.Count-1);
}
公共事件属性更改事件处理程序属性更改;
void OnNotifyPropertyChanged(字符串属性)
{
if(PropertyChanged==null)
返回;
PropertyChanged(此,新PropertyChangedEventArgs(property));
}
}
其他答案正确地解释了它不更新的原因。要强制更新,您可以将转换器更改为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();
}
}
现在,第二个绑定将通知在添加或删除项时绑定需要更新,但您可以忽略计数值而不使用它。您是否尝试过set{data=value;RaisePropertyChanged(“data”);}
?老实说,我将提供一个完全符合您需要的属性,并在VM中处理逻辑。使用转换器是一件很奇怪的事情,我尽量避免使用它。想想看,一个转换应该把一个值转换成另一个值,你正在把一个列表转换成一个数字。会议