需要基于第二个组合框的SelectedValue设置WPF MVVM组合框ItemsSource的SIMPLE工作示例



有人能给我看一个WPF MVVM应用程序的简单工作示例吗?该应用程序基于组合框a的SelectedItem设置组合框B的ItemsSource?

从我在这个网站上发现的情况来看,它变得太复杂了,太快了。

MVVM的"正确"方式是什么?

谢谢。

编辑我用滴滴的例子进行了更新。我的XAML摘录:

<ComboBox Name="BrowserStackDesktopOS" ItemsSource="Binding Platforms.AvailableBrowserStackDesktopOSes}" SelectedIndex="0" SelectedItem="{Binding Platforms.BrowserStackDesktopOSSelectedValue, Mode=TwoWay}"/>
<ComboBox Name="BrowserStackDesktopOSVersion" ItemsSource="{Binding Platforms.AvailableBrowserStackDesktopOSVersions}" SelectedIndex="0" SelectedItem="{Binding Platforms.BrowserStackDesktopOSVersionSelectedValue, Mode=TwoWay}"/>
<ComboBox Name="BrowserStackDesktopBrowser" ItemsSource="{Binding Platforms.AvailableBrowserStackDesktopBrowsers}" SelectedIndex="0" SelectedItem="{Binding Platforms.BrowserStackDesktopBrowserSelectedValue, Mode=TwoWay}"/>
<ComboBox Name="BrowserStackDesktopBrowserVersion" ItemsSource="{Binding Platforms.AvailableBrowserStackDesktopBrowserVersions}" SelectedIndex="0" SelectedItem="{Binding Platforms.BrowserStackDesktopBrowserVersionSelectedValue, Mode=TwoWay}"/>

还有我的代码示例:

public string BrowserStackDesktopOSSelectedValue {
        get { return (string)GetValue(BrowserStackDesktopOSSelectedValueProperty); }
        set { SetValue(BrowserStackDesktopOSSelectedValueProperty, value);
              AvailableBrowserStackDesktopOSVersions = AvailableBrowserStackDesktopPlatforms.GetOSVersions(BrowserStackDesktopOSSelectedValue);
              NotifyPropertyChanged("BrowserStackDesktopOSSelectedValue");
        }
    }

但是,当我为第一个组合框选择一个值时,什么都不会发生。我希望填充下一个组合框的Itemsource。

我做错了什么?

基本上,您需要在MVVM中公开用于组合框选择的值的2个集合和用于所选值的两个属性。

在开头只有第一个集合(如果填充了值)。当第一个选定值更改时,第二个集合将填充适当的值。下面是一个示例实现:

代码背后:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        //Set the data context of the window
        DataContext = new TestVM();
    }
}

public class TestVM : INotifyPropertyChanged
{
    #region Class attributes
    protected static string[] firstComboValues = new string[] { "Choice_1", "Choice_2" };
    protected static string[][] secondComboValues =
        new string[][] { 
                new string[] { "value_1_1", "value_1_2", "value_1_3" }, 
                new string[] { "value_2_1", "value_2_2", "value_2_3" } 
        };

    #endregion
    #region Public Properties
    #region FirstSelectedValue
    protected string m_FirstSelectedValue;
    /// <summary>
    ///  
    /// </summary>
    public string FirstSelectedValue
    {
        get { return m_FirstSelectedValue; }
        set
        {
            if (m_FirstSelectedValue != value)
            {
                m_FirstSelectedValue = value;
                UpdateSecondComboValues();
                NotifyPropertyChanged("FirstSelectedValue");
            }
        }
    }
    #endregion
    #region SecondSelectedValue
    protected string m_SecondSelectedValue;
    /// <summary>
    ///  
    /// </summary>
    public string SecondSelectedValue
    {
        get { return m_SecondSelectedValue; }
        set
        {
            if (m_SecondSelectedValue != value)
            {
                m_SecondSelectedValue = value;
                NotifyPropertyChanged("SecondSelectedValue");
            }
        }
    }
    #endregion
    #region FirstComboValues
    protected ObservableCollection<string> m_FirstComboValues;
    /// <summary>
    ///  
    /// </summary>
    public ObservableCollection<string> FirstComboValues
    {
        get { return m_FirstComboValues; }
        set
        {
            if (m_FirstComboValues != value)
            {
                m_FirstComboValues = value;
                NotifyPropertyChanged("FirstComboValues");
            }
        }
    }
    #endregion
    #region SecondComboValues
    protected ObservableCollection<string> m_SecondComboValues;
    /// <summary>
    ///  
    /// </summary>
    public ObservableCollection<string> SecondComboValues
    {
        get { return m_SecondComboValues; }
        set
        {
            if (m_SecondComboValues != value)
            {
                m_SecondComboValues = value;
                NotifyPropertyChanged("SecondComboValues");
            }
        }
    }
    #endregion
    #endregion
    public TestVM()
    {
        FirstComboValues = new ObservableCollection<string>(firstComboValues);
    }
    /// <summary>
    /// Update the collection of values for the second combo box
    /// </summary>
    protected void UpdateSecondComboValues()
    {
        int firstComboChoice;
        for (firstComboChoice = 0; firstComboChoice < firstComboValues.Length; firstComboChoice++)
        {
            if (firstComboValues[firstComboChoice] == FirstSelectedValue)
                break;
        }

        if (firstComboChoice == firstComboValues.Length)// just in case of a bug
            SecondComboValues = null;
        else
            SecondComboValues = new ObservableCollection<string>(secondComboValues[firstComboChoice]);
    }

    #region INotifyPropertyChanged implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion
}

以及相关的XAML

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="window" x:Class="Testing1.MainWindow">
    <Grid>
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center" Width=" 300">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition Height="10"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <ComboBox x:Name="FirstOne" ItemsSource="{Binding FirstComboValues}" SelectedItem="{Binding FirstSelectedValue, Mode=TwoWay}"/>
            <ComboBox x:Name="SecondOne" ItemsSource="{Binding SecondComboValues}" SelectedItem="{Binding SecondSelectedValue, Mode=TwoWay}" Grid.Row="2"/>
        </Grid>
    </Grid>
</Window>

正如您所看到的,组合框的SelectedValue属性在TwoWay模式下绑定,因此当组合框的SelectedValue属性更改时,它会更改VM端的值。在FirstSelectedValue属性设置程序中,调用UpdateSecondComboValues()方法来更新第二个组合框的值。

编辑:

发生这种情况是因为您混合了INotifPropertyChanged和DependencyObject。你应该从中选择一个。通常,您在VM中实现INotifyPropertyChanged,并且属性设置器中的代码将起作用。

但是,如果从DependencyObject继承,则不应在setter/getter中编写任何代码。TwoWay绑定永远不会调用它。它只会在内部调用GetValue(…)。为了能够对DependencyProperty更改执行操作,您应该使用属性更改处理程序以不同的方式声明它:

#region BrowserStackDesktopOSSelectedValue 
/// <summary>
/// BrowserStackDesktopOSSelectedValue  Dependency Property
/// </summary>
public static readonly DependencyProperty BrowserStackDesktopOSSelectedValue Property =
    DependencyProperty.Register("BrowserStackDesktopOSSelectedValue ", typeof(string), typeof(YourVM),
        new FrameworkPropertyMetadata((string)null,
            new PropertyChangedCallback(OnBrowserStackDesktopOSSelectedValue Changed)));
/// <summary>
/// Gets or sets the BrowserStackDesktopOSSelectedValue  property. This dependency property 
/// indicates ....
/// </summary>
public string BrowserStackDesktopOSSelectedValue 
{
    get { return (string)GetValue(BrowserStackDesktopOSSelectedValue Property); }
    set { SetValue(BrowserStackDesktopOSSelectedValue Property, value); }
}
/// <summary>
/// Handles changes to the BrowserStackDesktopOSSelectedValue  property.
/// </summary>
private static void OnBrowserStackDesktopOSSelectedValue Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    YourVM target = (YourVM)d;
    string oldBrowserStackDesktopOSSelectedValue  = (string)e.OldValue;
    string newBrowserStackDesktopOSSelectedValue  = target.BrowserStackDesktopOSSelectedValue ;
    target.OnBrowserStackDesktopOSSelectedValue Changed(oldBrowserStackDesktopOSSelectedValue , newBrowserStackDesktopOSSelectedValue );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the BrowserStackDesktopOSSelectedValue  property.
/// </summary>
protected virtual void OnBrowserStackDesktopOSSelectedValue Changed(string oldBrowserStackDesktopOSSelectedValue , string newBrowserStackDesktopOSSelectedValue )
{
    //Here write some code to update your second ComboBox content.
    AvailableBrowserStackDesktopOSVersions = AvailableBrowserStackDesktopPlatforms.GetOSVersions(BrowserStackDesktopOSSelectedValue);
}
#endregion

顺便说一句,我总是使用Dr WPF片段来编写DP,所以速度要快得多。

相关内容

  • 没有找到相关文章

最新更新