遵循MVVM模式,如何创建“设置”功能,在其他用户控件中设置数据绑定项值?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了遵循MVVM模式,如何创建“设置”功能,在其他用户控件中设置数据绑定项值?相关的知识,希望对你有一定的参考价值。
!!请先看看底部的第二个编辑!
我的问题的简化版本:我有两个简单的用户控件Apple和Banana(view)及其相应的视图模型,每个模型包含2个属性。我还有一个ListBox作为Apple和Banana属性的“设置”。
苹果:
<UserControl>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,20,0" Text="{Binding AppleID}"/>
<TextBlock Text="{Binding Size}"/>
</StackPanel>
</UserControl>
香蕉:
<UserControl>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,20,0" Text="{Binding BananaID}"/>
<TextBlock Text="{Binding Length}"/>
</StackPanel>
</UserControl>
Apple VM:
public class AppleViewModel : Notifier
{
private string appleID;
public string AppleID
{
get => appleID; set
{
appleID = value;
OnPropertyChanged("AppleID");
}
}
private int size;
public int Size
{
get => size; set
{
size = value;
OnPropertyChanged("Size");
}
}
}
香蕉VM:
public class BananaViewModel : Notifier
{
private string bananaID;
public string BananaID
{
get => bananaID; set
{
bananaID = value;
OnPropertyChanged("BananaID");
}
}
private int length;
public int Length
{
get => length; set
{
length = value;
OnPropertyChanged("Length");
}
}
}
主窗口看起来像这样:
<Window>
<StackPanel Orientation="Vertical">
<local:AppleControlxaml x:Name="apple"/>
<local:BananaControl x:Name="banana"/>
<ListBox>
</ListBox>
</StackPanel>
</Window>
为了更快地进行设置,我在mainwindow中的代码中分配了DataContext。在实际情况中,我使用了window viewmodel。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
apple.DataContext = new AppleViewModel()
{
AppleID = "Apple001",
Size = 10,
};
banana.DataContext = new BananaViewModel()
{
BananaID = "Banana002",
Length = 10
};
}
}
现在我希望listBox控件显示并允许用户设置被聚焦的用户控件的属性值。典型的交互将是Select / Mousedown Apple用户控制区域 - >更改列表框中的长度 - >查看Apple用户控件值已更改。
如果用户选择/ mousedown香蕉用户控制,他/她应该能够做同样的事情。
问题是:如何使用MVVM和数据绑定实现此设置功能?我尝试为要绑定的视图框的ItemsSource创建一个ObservableCollection,但是如何确保集合正确更新apple视图模型?
对不起,很长的帖子。我是stackoverflow的新手。
第二次编辑
我很抱歉,但我的描述可能会使问题更加混乱。属性应使用ItemsControl而不是ListBox。这是期望的行为。 The UI when apple user control is MouseDown The UI when banana user control is MouseDown
当用户更改属性中的值时,用户控件(苹果或香蕉)也应更新其值。
我怀疑我应该将Properties的ItemControl中的ItemsSource属性数据绑定到AppleVM和BananaVM的实际属性,但我不确定如何正确使用数据绑定。
这是更新后的MainWindow.xaml。其他代码在第一次编辑时大多没有变化
<Window>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel>
<local:AppleControl x:Name="apple1" MouseDown="apple1_MouseDown"/>
<local:BananaControl x:Name="banana1" MouseDown="banana1_MouseDown"/>
</StackPanel>
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Properties of selected item" Foreground="Blue" Margin="10"></TextBlock>
<ItemsControl Name="properties" Grid.Row="1" Margin="10">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding PropertyName}"/>
<TextBlock Text="{Binding PropertyValue}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Grid>
</Window>
我会根据你的问题理解我的想法。
MainWindow.xaml.cs
public partial class MainWindow : Window
{
private AppleViewModel appleViewModel;
public AppleViewModel AppleViewModel
{
get
{
return this.appleViewModel;
}
set
{
if (this.appleViewModel != value)
{
this.appleViewModel = value;
}
}
}
private BananaViewModel bananaViewModel;
public BananaViewModel BananaViewModel
{
get
{
return this.bananaViewModel;
}
set
{
if (this.bananaViewModel != value)
{
this.bananaViewModel = value;
}
}
}
public MainWindow()
{
InitializeComponent();
this.AppleViewModel = new AppleViewModel();
this.AppleViewModel.AppleID = "Apple001";
this.AppleViewModel.Size = 10;
this.BananaViewModel = new BananaViewModel();
this.BananaViewModel.BananaID = "Banana001";
this.BananaViewModel.Length = 10;
apple.DataContext = this.AppleViewModel;
banana.DataContext = this.BananaViewModel;
ObservableCollection<int> sizes = new ObservableCollection<int>();
for (int i = 0; i < 10; i++)
{
sizes.Add(i);
}
ListBox.ItemsSource = sizes;
}
private void ListBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (this.AppleViewModel.IsSelected)
{
this.AppleViewModel.Size = (int)ListBox.SelectedItem;
}
if (this.BananaViewModel.IsSelected)
{
this.BananaViewModel.Length = (int)ListBox.SelectedItem;
}
}
}
MainWindow.xaml
<StackPanel Orientation="Vertical">
<wpfApplication4:AppleControlxaml x:Name="apple"/>
<wpfApplication4:BananaControl x:Name="banana"/>
<ListBox SelectionChanged="ListBox_OnSelectionChanged" x:Name="ListBox">
</ListBox>
</StackPanel>
您的水果虚拟机应该有一个名为IsSelected的新属性,如:
private bool isSelected;
public bool IsSelected
{
get
{
return this.isSelected;
}
set
{
this.isSelected = value;
OnPropertyChanged("IsSelected");
}
}
你的水果控制也应该有这个
<CheckBox IsChecked="{Binding IsSelected}"/>
如果您不想使用此复选框控件,请告诉我,我会尝试找到更准确的答案
编辑以澄清您的编辑(xD):
假设您已经使用其Value及其Description属性创建了“SettingsVM”。现在,您要在ListBox上显示所选的水果设置。让我们走吧......每当你的水果变化,你的SettingsVM的属性也必须改变,以显示正确的水果。在“banana1_MouseDown”或“apple1_MouseDown”中,您必须使用其属性初始化SettingsVM,以便创建一个方法来执行此操作。
private void InitializeSettingsVM(int value, string description)
{
//Same like you do when you initialize your Banana/AppleVM in your MainWindow initialize.
this.SettingsVM.Value = value;
this.SettingsVM.Description = description;
}
在您的banana1_MouseDown / apple1_MouseDown中,您应该:
private void banana1_MouseDown(whateveryouhavehere)
{
//Whatever you do here
this.InitializeSettingsVM(this.BananaViewModel.Length,this.BananaViewModel.BananaID);
}
以上是关于遵循MVVM模式,如何创建“设置”功能,在其他用户控件中设置数据绑定项值?的主要内容,如果未能解决你的问题,请参考以下文章