9

我的 WinRT/C# XAML Metro 应用程序使用 Windows 8 Release Preview(安装了最新补丁)时遇到了一个奇怪的问题。我正在使用ComboBox,其值ItemsSourceSelectedValue绑定到 ViewModel 中的属性:

<ComboBox SelectedValue="{Binding MySelectedValue, Mode=TwoWay}"
          ItemsSource="{Binding MyItemsSource, Mode=OneWay}"
          Width="200" Height="30" />

后面的代码:

public MainPage()
{
    this.InitializeComponent();

    DataContext = new TestViewModel();
}

和一个非常简单的定义TestViewModel,使用字符串:

public class TestViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private IEnumerable<string> _myItemsSource = new List<string>
        {
            "Test Item 1",
            "Test Item 2",
            "Test Item 3"
        };
    public IEnumerable<string> MyItemsSource
    {
        get { return _myItemsSource; }
    }

    private string _mySelectedValue = "Test Item 2";
    public string MySelectedValue
    {
        get { return _mySelectedValue; }
        set
        {
            _mySelectedValue = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("MySelectedValue"));
            }
        }
    }
}

现在我认为这个简单的解决方案应该可以工作......但是当我启动应用程序时,SelectedValue="Test Item 2"没有出现,ComboBox是空的。通过设置断点,我注意到绑定值MyItemsSourceMySelectedValue在设置视图时从视图模型中正确检索DataContext。在此操作之后,该ComboBox.SelectedValue属性实际上设置为"Test Item 2",但它只是不显示!我还注意到,当我通过 UI 上的用户操作更改 ComboBox 中的选定值时,更改的值会显示在 ComboBox 中,并且 View Model 属性也会相应更新。MySelectedValue因此,除了View Model 属性的初始可视化之外,一切似乎都运行良好。我真的越来越绝望了……

现在虽然这是最简单的例子,但在原点我想将整个实体绑定到 ComboBox,设置DisplayMemberPathSelectedValuePath. 不幸的是,同样的问题发生了。

4

2 回答 2

30

我在示例中发现了问题:在 XAML 标记中,我在SelectedValue属性之前定义了ItemsSource属性。如果我以这种方式交换两个定义,它会起作用:

<ComboBox ItemsSource="{Binding MyItemsSource, Mode=OneWay}"
      SelectedValue="{Binding MySelectedValue, Mode=TwoWay}"
      Width="200" Height="30" />

这真的很奇怪也很烦人。现在我想知道:这是一个错误还是设计使然?我认为这是一个错误,因为无论 XAML 中定义的属性的顺序如何,控件都应该正常工作。

于 2012-07-14T12:29:19.873 回答
2

这是有效的解决方案:您可以在这里找到https://skydrive.live.com/?cid=b55690d11b67401d&resid=B55690D11B67401D!209&id=B55690D11B67401D!209

<ComboBox Width="300" Height="32" HorizontalAlignment="Left" DisplayMemberPath="Name"
                  VerticalAlignment="Top" ItemsSource="{Binding PersonCollection}" 
                  SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"></ComboBox>

ViewModle 类是

public class ViewModel:BaseViewModel
    {
        private Person selectedPerson;
        public Person SelectedPerson {
            get { return this.selectedPerson; }
            set { this.selectedPerson = value;
            this.RaisePropertyChanged("SelectedPerson");
            }
        }
        public ObservableCollection<Person> PersonCollection { get; set; }

        public ViewModel()
        {
            this.PersonCollection = new ObservableCollection<Person>();
            this.PopulateCollection();

            //setting first item as default one
            this.SelectedPerson = this.PersonCollection.FirstOrDefault();
        }

        private void PopulateCollection()
        {
            this.PersonCollection.Add(new Person { Name="Oscar", Email="oscar@sl.net" });
            this.PersonCollection.Add(new Person { Name = "Jay", Email = "jay@sl.net" });
            this.PersonCollection.Add(new Person { Name = "Viral", Email = "viral@sl.net" });
        }
    }
于 2012-07-14T09:45:23.580 回答