Combobox.SelectedItem绑定到嵌套属性

时间:2012-07-20 09:16:33

标签: wpf mvvm binding combobox

我正在使用MVVM做一个简单的WPF应用程序,我无法绑定到组合框的SelectedItem属性。 绑定属性的setter不会被调用,并且调试窗口中没有输出告诉我它无法绑定(我认为它能够)。 这是.NET 3.5,我做了一个小例子,它有同样的问题。

在XAML中:

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <ComboBox IsDropDownOpen="False" IsReadOnly="False" ItemsSource="{Binding Path=Printers}" SelectedIndex="0" SelectedItem="{Binding Path=Printer.SelectedPrinter, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Name="cmbPrinters" />
    </StackPanel>
</Window>

查看背后的代码:

using System.Windows;

public partial class Window1 : Window
{
    ViewModel viewmodel;

    public Window1()
    {
        viewmodel = new ViewModel();
        this.DataContext = viewmodel;
        InitializeComponent();
    }
}

查看型号:

using System;
using System.Collections.ObjectModel;

public class ViewModel
{
    public ViewModel()
    {
        Printers = new ObservableCollection<string>() { "test", "test2" };
        Printer = new PrinterViewModel();
    }

    public PrinterViewModel Printer { get; set; }
    public ObservableCollection<string> Printers { get; set; }
}

PrinterViewModel:

using System.Windows;
using System.Diagnostics;

public class PrinterViewModel : DependencyObject
{
    public string SelectedPrinter
    {
        get { return (string)GetValue(SelectedPrinterProperty); }
        set
        {
            SetValue(SelectedPrinterProperty, value);
            Debug.WriteLine("!!!!!! SelectedPrinter setter called");
        }
    }

    public readonly DependencyProperty SelectedPrinterProperty =
        DependencyProperty.Register("SelectedPrinter", typeof(string), typeof(PrinterViewModel), new UIPropertyMetadata());
}

谁能看到我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

这里的问题是您对Silverlight依赖属性系统的工作方式存在误解。

当依赖项属性的值更改时,Silverlight不会遍历您定义的属性(例如SelectedPrinter)来设置依赖项属性的值。 Silverlight依赖项属性机制会跟踪依赖项属性的所有值,当其中一个属性的值发生更改时,Silverlight会直接更改其值,而不会调用您的代码来执行此操作。特别是,它不会调用您的属性设置器。这可以解释为什么你的调试信息没有出现。

使用依赖项属性的属性中的getter(例如SelectedPrinter属性)应仅包含对GetValue的调用,并且setter应仅包含对SetValue的调用。您不应该向getter或setter添加任何代码,因为这样做无法达到您想要的效果。

此外,您正在视图模型层中使用依赖项属性。这不是他们打算使用的地方。依赖项属性仅用于视图层。您的视图模型类应该是implementing INotifyPropertyChanged,而不是扩展DependencyObject

可以将两个依赖项属性绑定在一起。这是允许的,有时在视图层中将两个依赖项属性连接在一起非常有用。事实上,您的示例中的绑定正在工作,这解释了为什么您没有收到有关绑定问题的任何消息。

答案 1 :(得分:1)

为什么在执行mvvm时从DependencyObject继承?`

public class PrinterViewModel : INotifyPropertyChanged
{
   private string _selected;
   public string SelectedPrinter
   {
      get { return this._selected; }
      set
      {
        _selected= value;
        OnPropertyChanged("SelectedPrinter");
      }
   }
}

现在您的代码应该正常工作