2014-01-14 4 views
0

Я пытаюсь понять концепцию DataBinding со списком с объектом.C# WPF - ComboBox DataBinding

У меня есть следующий класс:

public class employmentApplication 
{ 
    private byte appType = 0; // 1 = normal; 2 = expedited 

    public byte AppType 
    { 
    get { return appType ; } 
    set 
    { 
     appType = value; 
     this.OnPropertyChanged("AppType"); 
    } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    void OnPropertyChanged(string propName) 
    { 
    if (this.PropertyChanged != null) 
     this.PropertyChanged(
     this, new PropertyChangedEventArgs(propName)); 
    } 
} 

Мой XAML для комбобокса является

<ComboBox> 
    <ComboBoxItem Content="Normal" /> 
    <ComboBoxItem Content="Expedited" /> 
</ComboBox> 

Я не уверен, с чего начать, чтобы связать свою выпадающий к APPTYPE, так как он должен преобразовать его от строки («Нормальный», «Ускоренный») до байта (0, 1) и обратно между объектом и выпадающим списком.

Спасибо за любую помощь заранее!

ответ

1

Мой совет использовать ValueConverter. Это более гибкое решение, чем использование значений Tag, и это выглядит красиво, потому что вы отделяете логику преобразования в своем классе. Также я заметил, что в вашем классе данных вы объявили событие PropertyChanged, но не реализовали интерфейс INotifyPropertyChanged, поэтому в этом случае вы не можете иметь двухстороннюю привязку. Полный пример:

Ваш класс данных (с моими исправлениями)

public class EmploymentApplication : INotifyPropertyChanged 
{ 
    private byte appType = 0; // 1 = normal; 2 = expedited 

    public byte AppType 
    { 
     get { return appType; } 
     set 
     { 
      appType = value; 
      OnPropertyChanged("AppType"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    void OnPropertyChanged(string propName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
    } 
} 

Значение преобразователя

public class AppTypeConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var b = (byte)value; 
     if (b == 1) return "Normal"; 
     if (b == 2) return "Expedited"; 
     return string.Empty; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var strValue = (string) value; 
     byte result = 0; 
     if (strValue.Equals("Normal", StringComparison.Ordinal)) 
     { 
      result = 1; 
     } 
     else if (strValue.Equals("Expedited", StringComparison.OrdinalIgnoreCase)) 
     { 
      result = 2; 
     } 
     return result; 
    } 
} 

xaml.cs

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new EmploymentApplication(); 
    } 
} 

Xaml

<Window x:Class="WpfConvertion.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfConvertion" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <local:AppTypeConverter x:Key="Converter"></local:AppTypeConverter> 
</Window.Resources> 
<Grid> 
    <ComboBox Height="20" SelectedValue="{Binding AppType, Converter={StaticResource Converter}}" SelectedValuePath="Content"> 
     <ComboBoxItem>Normal</ComboBoxItem> 
     <ComboBoxItem>Expedited</ComboBoxItem> 
    </ComboBox> 
</Grid> 

Обратите внимание на этой линии: XMLNS: локальные = "CLR-имена: WpfConvertion". Вы должны установить свое собственное пространство имен вместо моего WpfConvertion.

+0

Это делает то, что я хочу, однако, я ищу способ изменить преобразователь значений, чтобы быть более динамичным. Это всего лишь пример того, что я пытаюсь сделать. У меня будут другие комбинированные поля с двумя значениями (0,1), но с другим отображаемым текстом. – user3175176

3

Вы могли бы сделать это несколькими способами, однако это простое решение для того, что вы просили. Обратите внимание: ваш DataContext должен быть установлен в ваш экземпляр класса, который вы хотите представить.

<ComboBox SelectedValue="{Binding AppType, Mode=TwoWay}" 
      SelectedValuePath="Tag"> 
    <ComboBoxItem Content="Normal" Tag="0"/> 
    <ComboBoxItem Content="Expedited" Tag="1"/> 
</ComboBox> 

SelectedValue является переплетены в вашей собственности, и SelectedValuePath это свойство ComboBoxItem (в данном случае), который будет представлять выбранное значение.

Это очень простое решение, и вам может потребоваться его изменить для ваших нужд. Кроме того, я бы рассмотрел использование Enum для представления этих данных. Это будет немного легче понять, что вы пытаетесь сделать в коде.

Редактировать


Ниже приведен пример использования enum с приведенным выше примером. Я собираюсь использовать ваш уже существующий код в качестве базы.

Создайте перечисление (желательно в новом файле).

public enum AppType 
{ 
    Normal, 
    Expedited 
} 

Теперь измените свойство использовать перечисления

public AppType AppType 
{ 
    get 
    { 
     return appType; 
    } 
    set 
    { 
     if(Equals(appType, value)) return; 
     appType = value; 

     OnPropertyChanged("AppType"); 
    } 
} 

Теперь вы можете использовать мой пример выше, но с перечислением:

<ComboBox SelectedValue="{Binding AppType, Mode=TwoWay}" 
      SelectedValuePath="Tag"> 
    <ComboBoxItem Content="Normal" Tag="{x:Static local:AppType.Normal}"/> 
    <ComboBoxItem Content="Expedited" Tag="{x:Static local:AppType.Expedited"/> 
</ComboBox> 

Следующая славен имея немного больше контроля над тем, что отображается в ComboBox. Однако вы также можете отображать каждое значение enum, что приятно, потому что если вы добавите значения enum в будущем, они автоматически появятся в ComboBox. See this question and answer для способа сделать это.

+0

Не могли бы вы рассказать о том, что вы имеете в виду, используя Enum? Я хочу сделать это правильно. Благодаря! – user3175176

+0

Конечно, я опубликую его как отредактировать, чтобы ответить здесь через секунду. – deloreyk

0

Есть несколько способов для достижения этой цели наиболее простых может быть, чтобы добавить привязку к APPTYPE с SelectedIndex собственностью вашего ComboBox Обратите внимание, что вы должны добавить INotifyPropertyChanged, чтобы ваше связывание работы

и в коде позади сделайте следующее

namespace WpfApplication8 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     employmentApplication emp = new employmentApplication(); 

     public MainWindow() 
     { 
      InitializeComponent(); 
      this.DataContext = emp; 
     } 
    } 
    public class employmentApplication:INotifyPropertyChanged 
    { 
     private byte appType = 0; // 1 = normal; 2 = expedited 

     public byte AppType 
     { 
      get { return appType; } 
      set 
      { 
       appType = value; 
       this.OnPropertyChanged("AppType"); 
      } 
     } 



     public event PropertyChangedEventHandler PropertyChanged;   

     void OnPropertyChanged(string propName) 
     { 
      if (this.PropertyChanged != null) 
       this.PropertyChanged(
       this, new PropertyChangedEventArgs(propName)); 
     } 
    } 
} 
+0

Это будет работать нормально, однако я считаю, что он не очень надежный, и вы вынуждаете себя добавлять дополнительные свойства для поддержки одного элемента управления. – deloreyk

0

Самый простой способ: если вы нормальное значение равно 0, а ваше ускоренное значение равно 1, используйте SelectedIndex для привязки.

<ComboBox SelectedIndex="{Binding AppType}" >

0

Вы можете использовать конвертер или теги, как показали другие ответы. Но вы также можете определить свой источник-источник как класс, а не полагаться на размахивание руками, чтобы связать целые числа со строками. Так что ваши пункт элементы источника может быть классом, как это:

public class AppType 
{ 
    public string Name; 
    public byte Type; 
} 

Вы можете использовать SelectedValue и SelectedValuePath связывания на вашем выпадающий список, чтобы определить, какие изменения в вашей DataContext, и какое свойство используется в списке поиска.

<ComboBox 
    ItemSource = {Binding ListOfAppTypes} 
    SelectedValue="{Binding Type, Mode=TwoWay}" 
    SelectedValuePath="Name"> 
</ComboBox> 

Вы можете также определить шаблон для вашего Combobox, где вы получите больший контроль над тем, как отображается список поиска предметов.