【问题标题】:Populate one combobox based on selection of another根据对另一个组合框的选择填充一个组合框
【发布时间】:2010-08-12 15:23:26
【问题描述】:

我正在学习 wpf mvvm,并且一直在努力解决我觉得可能很简单但无法自己解决的问题。

我想要的是能够在填充的组合框中选择一个项目,然后根据该选择填充另一个组合框。我似乎无法加载第二个组合框以响应选择。

我已经包含了一个包含 2 个组合框和一个文本块的示例。当我运行应用程序并在第一个组合中选择一个项目时,文本块会根据绑定进行更新,但我不知道在哪里调用代码来更新第二个组合框。

我尝试添加对 SelectedString 属性设置器的调用,但似乎从未调用过。我确定我错过了一些简单的东西,但我需要有人帮助揭开面纱!

我已经尝试过其他帖子的建议,但到目前为止我没有成功。

这是视图的 xaml:

<Window x:Class="ThrowAwayMVVMApp.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Main Window" Height="400" Width="800">

    <DockPanel>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="60*" />
                <RowDefinition Height="282*" />
            </Grid.RowDefinitions>
            <!-- Add additional content here -->
            <ComboBox ItemsSource="{Binding MyStrings}" SelectedItem="{Binding Path=SelectedString, Mode=TwoWay}" Height="23" HorizontalAlignment="Left" Margin="18,24,0,0" Name="comboBox1" VerticalAlignment="Top" Width="204" />
            <TextBlock Text="{Binding SelectedString}" Height="23" HorizontalAlignment="Left" Margin="276,24,0,0" Name="textBlock1" VerticalAlignment="Top" Width="227" Background="#FFFAE7E7" />
            <ComboBox ItemsSource="{Binding ResultStrings}"  Height="23" HorizontalAlignment="Left" Margin="543,25,0,0" Name="comboBox2" VerticalAlignment="Top" Width="189" />
        </Grid>
    </DockPanel>
</Window>

这是视图模型:

public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        this.MyStrings = new ObservableCollection<string>
            {
                "One",
                "Two",
                "Three",
                "Four",
                "Five"
            };
    }

    public ObservableCollection<string> MyStrings { get; set; }
    public ObservableCollection<string> ResultStrings { get; set; }

    public string SelectedString
    {
        get { return (string)GetValue(SelectedStringProperty); }
        set 
        { 
            SetValue(SelectedStringProperty, value);
            this.ResultStrings = getResultStrings(value);
        }
    }

    // Using a DependencyProperty as the backing store for SelectedString.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SelectedStringProperty =
        DependencyProperty.Register("SelectedString", typeof(string), typeof(MainViewModel), new UIPropertyMetadata(""));


    private ObservableCollection<string> getResultStrings(string input)
    {
        ObservableCollection<string> result = null;

        if (input == "Three")
        {
            result = new ObservableCollection<string> { "Six", "Seven", "Eight" };
        }
        else
        {
            result = new ObservableCollection<string> { "Nine", "Ten", "Eleven" };
        }

        return result;
    }
}

【问题讨论】:

  • 为什么要在 ViewModel 中声明 DP,通常它意味着要在您绑定的 Control 中?

标签: wpf data-binding mvvm


【解决方案1】:

SelectedString 依赖属性实现错误:你应该注册 PropertyChangedCallback 以便在直接访问 DP 而不是使用 CLR 属性集时得到通知(参见http://msdn.microsoft.com/en-us/library/system.windows.propertychangedcallback.aspx);这样即使直接使用 DP 也可以更改相关的集合。

当绑定依赖属性(如 SelectedString)时,WPF 绑定不使用 CLR 属性设置器,因此您永远不会调用 getResultStrings

顺便说一句,我会考虑在 View Models 上使用 POCO 方法,实现 INotifyPropertyChanged:DP 编写起来很痛苦,并且会给 VM 添加很多噪音(除了对 System.Windows 的讨厌依赖)。

查看这篇博文进行广泛比较:http://kentb.blogspot.com/2009/03/view-models-pocos-versus.html

【讨论】:

    【解决方案2】:

    试试

    private string selectedString;
    public string SelectedString
    {
        get { return selectedString; }
        set 
        { 
            if (selectedString == value) return;
            selectedString = value;
            // Required for the UI to know the change was successful
            RaisePropertyChanged("SelectedString");
            LoadStringResults(value);
        }
    }
    
    private ObservableCollection<string> resultStrings;
    public ObservableCollection<string> ResultStrings
    {
        get { return resultStrings; }
        set 
        { 
            if (resultStrings== value) return;
            resultStrings= value;
            // Required for databinding to know that ResultStrings changed
            // Previously you changed this property without updating the UI
            RaisePropertyChanged("ResultStrings");
        }
    }
    
    private void LoadStringResults(string input)
    {
        ObservableCollection<string> result = null;
    
        if (input == "Three")
        {
            result = new ObservableCollection<string> { "Six", "Seven", "Eight" };
        }
        else
        {
            result = new ObservableCollection<string> { "Nine", "Ten", "Eleven" };
        }
    
        ResultStrings = result;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-29
      相关资源
      最近更新 更多