gpt4 book ai didi

c# - 如何在 ItemsControl 组中绑定(bind)小计

转载 作者:行者123 更新时间:2023-11-30 12:15:32 25 4
gpt4 key购买 nike

想象一下这个类似 DTO 的类:

class LineItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Description { get; set; }

private decimal m_Amount;
public decimal Amount
{
get { return m_Amount; }
set
{
if (m_Amount == value)
return;
m_Amount = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Amount"));
}
}
}

像这样的绑定(bind):

<ItemsControl ItemsSource="{Binding LineItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel>
<TextBox Text="{Binding Amount}"
DockPanel.Dock="Right" Width="50" />
<TextBlock Text="{Binding Description}" />
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

这看起来像:

enter image description here

现在,我想要底部的总数。此外,我希望它在 Amount 更改时更新。

像这样:

<TextBlock HorizontalAlignment="Right"
Text="{Binding LineItems,
Converter={StaticResource MyConverter}}" />

为此:

enter image description here

但是什么是 MyConverter?而且,这是否是一种正确的方法?

我的问题:

这不起作用,因为转换器仅在第一次绑定(bind)时被调用。我希望它反射(reflect)用户更改,并且我需要处理未知数量的 LineItems。当然我不是第一个打这个的。 有办法吗?

最佳答案

您可以改为绑定(bind)到专门表示 AverageAmount 的属性(在您的“ View 模型”上),并确保在 PropertyChanged 上为每个 LineItem 您发送了 AverageAmount 属性的更改通知,以允许模型计算值和 UI 以重新获取新值。 Maleak's example shows exactly that .

但是,仔细考虑这样做的开销,我会看像 BindableLinq 这样的东西。或 Obtics (或 Continuous Linq )应该处理所有的依赖分析和变更通知。我们使用 BindableLinq 取得了巨大的成功,尽管此时它并没有被启动它的人积极维护。

编辑:

举一个不使用我上面提到的那些库的后端示例(它删除了处理集合和属性更改事件的管道):

public class ItemListViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private readonly ObservableCollection<ItemViewModel> _items = new ObservableCollection<ItemViewModel>();

public ItemListViewModel()
{
_items.CollectionChanged += OnItemsChanged;
}

public ICollection<ItemViewModel> Items { get { return _items; } }

private void OnItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
e.NewItems.Cast<ItemViewModel>().ToList().ForEach(iv => iv.PropertyChanged += OnItemPropertyChanged);
break;
case NotifyCollectionChangedAction.Remove:
e.OldItems.Cast<ItemViewModel>().ToList().ForEach(iv => iv.PropertyChanged -= OnItemPropertyChanged);
break;
default:
throw new NotImplementedException();
}
}

private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Value")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("AverageValue"));
}
}

public double AverageValue
{
get { return Items.Average(iv => iv.Value); }
}
}

public class ItemViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Family { get; set; }
private int m_Value;
public int Value
{
get { return m_Value; }
set
{
if (m_Value == value)
return;

m_Value = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Value"));
}
}
}

然后 XAML 中的 ItemsControl 直接绑定(bind)到 View 模型的 Items 属性,平均值绑定(bind)到 AverageValue 属性。它现在将处理所需的通知。

要在另一个级别添加分组,您必须引入另一个类“ItemGroupViewModel”,该类将监视父项集合的更改。我会向所有项目添加属性更改监听器,然后如果他们更改其 Family 属性,则从本地 Items 集合中添加/删除。如果他们更改其 Value 属性,则为 AverageValue 属性触发 PropertyChanged。

注意:BindableLinq 也支持分组操作。

关于c# - 如何在 ItemsControl 组中绑定(bind)小计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7154758/

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