C# 遵循MVVM模式,如何创建;“设置”;在其他用户控件中设置数据绑定项值的函数?

C# 遵循MVVM模式,如何创建;“设置”;在其他用户控件中设置数据绑定项值的函数?,c#,wpf,xaml,mvvm,data-binding,C#,Wpf,Xaml,Mvvm,Data Binding,!!请首先查看底部的第二次编辑 我的问题的简化版本:我有两个简单的用户控件Apple和Banana(视图),它们对应的视图模型分别包含两个属性。我还有一个列表框作为苹果和香蕉属性的“设置” 苹果公司: <UserControl> <StackPanel Orientation="Horizontal"> <TextBlock Margin="0,0,20,0" Text="{Binding AppleID}"/>

!!请首先查看底部的第二次编辑

我的问题的简化版本:我有两个简单的用户控件Apple和Banana(视图),它们对应的视图模型分别包含两个属性。我还有一个列表框作为苹果和香蕉属性的“设置”

苹果公司:

<UserControl>  
    <StackPanel Orientation="Horizontal">  
        <TextBlock Margin="0,0,20,0" Text="{Binding AppleID}"/>  
        <TextBlock Text="{Binding Size}"/>  
    </StackPanel>  
</UserControl>  
香蕉虚拟机:

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>
现在我希望listBox控件显示并允许用户设置用户控件的属性值。典型的交互是选择/鼠标向下移动Apple用户控件区域->在列表框中更改长度->查看Apple用户控件值是否更改

如果用户选择/mousedown Banana用户控件,他/她也应该能够这样做

问题是:如何使用MVVM和数据绑定实现此设置功能?我尝试为viewbox的ItemsSource创建一个ObservableCollection以绑定到,但是如何确保集合正确更新apple视图模型

抱歉发了这么长的邮件。我是个新手


第二次编辑

我很抱歉,但我的描述可能会让问题变得更加混乱。属性应使用ItemsControl而不是ListBox。以下是所需的行为。

当用户更改属性中的值时,用户控件(苹果或香蕉)也应更新其值

我怀疑应该将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;
        }
    }
}
你的水果控制也应该有这个

<CheckBox IsChecked="{Binding IsSelected}"/>
在banana1_MouseDown/apple1_MouseDown中,您应该执行以下操作:

private void banana1_MouseDown(whateveryouhavehere)
   {
     //Whatever you do here
     this.InitializeSettingsVM(this.BananaViewModel.Length,this.BananaViewModel.BananaID);
   }

非常感谢您的回复!但是,listbox的ItemsSource是否可以直接数据绑定到appleVM或bananaVM属性,而不是Int集合?还请检查我的第二次编辑以了解所需的行为。在banana1_MouseDown和apple1_MouseDown中,您可以更改“属性”itemcontrol itemsource。因为它们是不同的VM,所以您应该创建另一个VM将其绑定到itemsControl,比如说“itemsControl VM”,它将有一个描述和一个值(?),然后当您更改选择时,使用所需的值初始化itemsControl VM。我希望我能解释我自己。。。如果我没有告诉我,我会发布一个新的答案和代码。这是否意味着我必须手动确保当某些值更改时,appleVM、bananaVM和新的“propertiesVM”在代码中同步?假设用户更改了苹果的“属性”,那么后面的属性VM和appleVM都必须更改?就是这样。你有一个列表框,其中有一个带有VM的itemsource集合,所以每次你的水果改变时,你都必须更新你的设置SVM。您可以创建一个私有方法,如private void InitializeSettingsVM(int size,string description),当您选择水果时,您可以调用该方法并设置settingsVM属性。这样做,你“更接近”固体,它将更容易阅读。这是应该做的。我会尽快更新我的答案,以便你能看到它。检查编辑,如果它有助于你/回答你的问题,请检查它作为正确答案/投票
    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;
        }
    }
}
 <StackPanel Orientation="Vertical">
        <wpfApplication4:AppleControlxaml x:Name="apple"/>
        <wpfApplication4:BananaControl x:Name="banana"/>
        <ListBox SelectionChanged="ListBox_OnSelectionChanged" x:Name="ListBox">
        </ListBox>
    </StackPanel>
private bool isSelected;
    public bool IsSelected
    {
        get
        {
            return this.isSelected;

        }
        set
        {
            this.isSelected = value;
            OnPropertyChanged("IsSelected");
        }
    }
<CheckBox IsChecked="{Binding IsSelected}"/>
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;
    }
private void banana1_MouseDown(whateveryouhavehere)
   {
     //Whatever you do here
     this.InitializeSettingsVM(this.BananaViewModel.Length,this.BananaViewModel.BananaID);
   }