我有一个绑定到“ItemsView”视图的“ItemsViewModel”ViewModel。在ViewModel中,我有完整的属性List 'ItemsList',它绑定到ItemsControls ItemsSource。然后将DataTemplate设置为名为“ItemControl”的UserControl。
这工作得很好,在UserControl中,我可以绑定到模型中的公共属性,我假设根据我所读到的内容,这是最合适的方法,但我不确定如何将按钮命令传播回ViewModel。
在下面的代码中,我使用的方法是使用'Finderstor',但这感觉不对。{Binding AddItemCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl, AncestorLevel=2}}">
我也读过关于将整个UserControl绑定到它自己的ViewModel的不同意见。例如,如果UserControl现在需要有10个按钮,这使得它变得复杂,而这个论点是说UserControl应该简单,但为什么它们必须简单呢?我对UserControls的使用是,我想创建一个“视图”,我想重复10次,也许100次,也许500次,如果这个视图很复杂,有多个按钮和控件类型,它是否保证它自己的ViewModel?
任何帮助或信息来源,这将是非常感谢!
视图模型:
public class ItemsViewModel : ViewModelBase
{
public ICommand AddItemCommand { get; }
public ItemsViewModel()
{
AddItemCommand = new CommandBase(AddItem);
}
private void AddItem(object obj)
{
*Code to run on button press*
}
private List<ItemList> itemsList;
public List<ItemList> ItemsList
{
get
{
return itemsList;
}
set
{
itemsList = value;
OnPropertyChanged(nameof(ItemsList));
}
}
}
产品型号:
public class ItemList
{
public string Name { get; set; }
public double Amount { get; set; }
}
public class ItemLists
{
public List<ItemList> itemLists { get; set; }
public double totalAmount
{
get
{
double totalAmount = 0;
foreach (var item in itemLists)
{
totalAmount = totalAmount + item.Amount;
}
return totalAmount;
}
}
}
检视:
<ItemsControl ItemsSource="{Binding ItemsList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<usercontrol:ItemControl/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
用户控制:
<Button Command="{Binding AddItemCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl, AncestorLevel=2}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text={Binding Name}/>
<TextBlock Grid.Row="1" Text={Binding Amount}/>
</Grid>
</Button>
1条答案
按热度按时间arknldoa1#
您的问题涉及MVVM(模型-视图-视图模型)架构的一个重要方面:当视图模型需要响应用户交互时,如何处理视图中的用户交互。您有几个选项可以在不使用RelativeSource方法的情况下实现这一点:
UserControl-ViewModel配对:一种常见的方法是让每个UserControl与自己的ViewModel配对。在您的示例中,您有一个ItemControl UserControl,它表示ItemsList中的一个项。此UserControl可以有自己的ViewModel,这允许它处理自己的交互。
为ItemControl创建ViewModel(例如,ItemViewModel)。在此ViewModel中,定义AddItemCommand和该特定项所需的其他属性。将ItemControl的DataContext设置为ItemViewModel的示例。直接在ItemControl中将Button的Command绑定到AddItemCommand。这种方法允许每个项都有自己的ViewModel,如果项具有复杂的交互和数据需求,这种方法尤其有用。
传递命令:如果不希望为每个ItemControl创建单独的ViewModel,则可以将AddItemCommand从父ItemsViewModel传递到ItemsList中的每个ItemControl。您可以通过将ItemControl中的AddItemCommand绑定到一个属性来实现这一点,该属性保存对来自父ViewModel的命令的引用。
在ItemsViewModel中,可以循环访问ItemsList并为列表中的每个项设置此属性。然后,在ItemControl中,可以绑定到此属性。
这种方法允许您为每个项重用相同的ItemControl及其ViewModel,同时仍在父ViewModel中处理命令。
以下是选项2的示例:
在ItemsViewModel中,创建一个属性来保存AddItemCommand:
在ItemsViewModel构造函数中,初始化AddItemCommand:
在ItemsViewModel中,填充ItemsList时,为每个项设置AddItemCommand属性:
在ItemControl中,将Button的Command绑定到AddItemCommand属性:
(XML)
在ItemList类中,添加一个属性来保存命令:
这样,每个ItemControl都将使用父ItemsViewModel中的相同AddItemCommand,并且您不需要依赖RelativeSource来查找命令。