2016-05-05 68 views
0

我有一個組合框綁定到對象的集合。這些對象具有屬性布爾值IsSelected,該屬性指定當前是否選擇要在ComboBox文本區域中顯示的對象。組合框,WPF非常新

爲了使它使用IsSelected布爾屬性來顯示ComboBox中的默認項目,我添加了一個類似下面的ValueConverter類。

public class SelectedItemConverter : IValueConverter 
    { 

     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (value != null && value is IEnumerable<Car>) 
      { 
       return ((IEnumerable<Car>)value).Where(n => n.IsSelected).FirstOrDefault(); 
      } 
      return null; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (value != null && value is Car) 
      { 
       return value; 
      } 
      return null; 
     } 
    } 

我ComboBox位於UserContrl及其XAML是:

<ComboBox ItemsSource="{Binding CarsList}" 
      SelectedItem="{Binding CarsList, Converter={StaticResource selectedItemConverter}}" 
      DisplayMemberPath="Name"> 
</ComboBox> 

我使用的SelectedItem,因爲我的車對象有IsSelected是布爾和它所代表的汽車是否在組合框的文本區域中可見, 。出於這個原因,我有上面的ValueConverter使用該布爾值來正確返回對象。

這很好,當ComboBox加載時,IsSelected = True的對象將顯示在ComboBox文本區域中。但是,如果我展開下拉菜單並選擇另一個對象,則該對象將顯示,但ComboBox會獲得一個紅色邊框,據我所知,這意味着存在一些驗證問題。

我該如何解決這個問題?

我見過很多例子,但他們都沒有解決布爾屬性IsSelected用來確定在ComboBox中顯示哪個對象的問題。

我該如何解決這個問題?

+1

也許問題是'ConvertBack'功能,它應該返回'IEnumerable的 CarsList'。無論如何,我認爲你應該用這種方式重新考慮對'SelectedItem'的綁定。 – bars222

+0

你是對的,ConvertBack正在返回Car實例而不是CarList實例。但問題是我沒有CarList實例,因爲它沒有傳遞到ConvertBack。所以不知道如何讓它返回。 – pixel

+1

我認爲@Bolu建議如何更改綁定的好方法。否則,您可以嘗試將'CarList'作爲'ConverterParameter'傳遞(如果'CarList'集合永遠不會更改,您可以在xaml中像定義資源那樣定義它),但這是奇怪複雜的方式。 – bars222

回答

1

在WPF中,使用ComboBox的一個常見的做法是如下:

在視圖模型

  • 定義集合在你的虛擬機屬性(如你爲 CarsList
  • 將選定項目定義爲虛擬機中的一個屬性(使用 其他屬性,例如:SelectedCar

在查看

  • 綁定ItemsSource到 '收集' 屬性。
  • SelectedItem綁定到'selected item'屬性。

例如,

<ComboBox ItemsSource="{Binding CarsList}" 
      SelectedItem="{Binding SelectedCar}" 
      DisplayMemberPath="Name"> 
</ComboBox> 

如果你想設置選擇一個默認的項目,您只需設置SelectedCar屬性到該項目。當用戶更改選擇時,您將始終可以從SelectedCar屬性中獲取所選項目。

編輯:簡單的工作例如:

C#:

using System; 
using System.Collections.Generic; 
using System.Windows; 
using System.ComponentModel; 
using System.Collections.ObjectModel; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      MyViewModel mvm = new MyViewModel() 
      { 
       CarsList = new ObservableCollection<Car>() 
       { 
        new Car() { Name = "Car1" }, 
        new Car() { Name = "Car2" }, 
        new Car() { Name = "Car3" }, 
        new Car() { Name = "Car4" } 
       } 
      }; 
      this.DataContext = mvm; 
     } 
    } 

    public class MyViewModel : ObservableObject 
    { 
     private Car _selectedcar; 
     public ObservableCollection<Car> CarsList 
     { 
      get; 
      set; 
     } 

     public Car SelectedCar 
     { 
      get { return _selectedcar; } 
      set 
      { 
       if (value != _selectedcar) 
       { 
        _selectedcar = value; 
        RaisePropertyChanged("SelectedCar"); 
       } 
      } 
     } 


    } 

    public class Car : ObservableObject 
    { 
     private string _name; 
     public string Name 
     { 
      get { return _name; } 
      set 
      { 
       if (value != _name) 
       { 
        _name = value; 
        RaisePropertyChanged("Name"); 
       } 
      } 
     } 
    } 

    public class ObservableObject : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
     { 
      var handler = this.PropertyChanged; 
      if (handler != null) 
      {     
       handler(this, e); 
      } 
     } 

     protected void RaisePropertyChanged(String propertyName) 
     { 
      OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

XAML:

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="300" Width="300"> 
    <StackPanel Orientation="Vertical"> 
     <ComboBox ItemsSource="{Binding CarsList}" 
      SelectedItem="{Binding SelectedCar}" 
      DisplayMemberPath="Name"> 
     </ComboBox> 
     <TextBlock Text="{Binding SelectedCar.Name}"/> 
    </StackPanel> 
</Window> 

結果:TextBlock文本將更新時選擇的ComboBox改變。

Text in TextBlock updated when user select from ComboBox

+0

你介意多鑽一下嗎?你有沒有使用ComboBox的好例子?非常感謝 – pixel

+0

非常感謝Bolu。這非常有幫助。 – pixel

1

我將使用ComboBox的SelectionChanged事件來更新綁定列表中每個項目的IsSelected屬性,只將新選擇設置爲'True',將所有其他項設置爲'False'。

這意味着你不需要一個轉換器,其中@ bars222指出目前沒有正確返回你綁定到的可枚舉類型。

請注意,當您將項目的「IsSelected」屬性設置爲「True」時,這不會允許ComboBox更新所選項目 - 但您應該通過將combox的SelectedItem直接綁定到公共SelectedCar屬性在ViewModel上。加載視圖模型時,您可以通過檢查列表來初始化此SelectedCar,並將相應的項目顯示爲選中狀態。

+0

我想弄清楚爲什麼轉換器不能返回正確的值。謝謝安德魯。 – pixel

-1

您似乎想將MVVM模式應用於您的設計。 我建議你不需要轉換器,你可以在你的視圖模型中管理你的集合。