简体   繁体   English

C#WPF-ComboBox数据绑定

[英]C# WPF - ComboBox DataBinding

I am trying to understand the concept of DataBinding a combobox with an object. 我试图理解DataBinding带对象的组合框的概念。

I have the following class: 我有以下课程:

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));
  }
}

My xaml for the combobox is 我对组合框的xaml是

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

I am not sure where to begin to bind my combobox to the AppType since it has to convert it from a string ("Normal", "Expedited") to a byte (0, 1) and back between the object and the combobox. 我不确定从何处开始将组合框绑定到AppType,因为它必须将其从字符串(“ Normal”,“ Expedited”)转换为字节(0、1),然后在对象和组合框之间转换。

Thanks for any help in advance! 感谢您的任何帮助!

You could do this several ways, however here is a simple solution todo what you have asked. 您可以通过多种方式执行此操作,但是这里有一个简单的解决方案可以执行您所要求的操作。 Note, your DataContext will need to be set to your instance of the class you want to represent. 注意,您需要将DataContext设置为您要表示的类的实例。

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

SelectedValue is binded to your property, and SelectedValuePath is the property of ComboBoxItem (in this case) that will represent the selected value. SelectedValue绑定到您的属性,而SelectedValuePathComboBoxItem的属性(在本例中),它将代表所选值。

This is a very simple solution, and you may need to alter it for your needs. 这是一个非常简单的解决方案,您可能需要根据需要对其进行更改。 Additionally, I would consider using an Enum to represent this data. 另外,我将考虑使用Enum来表示此数据。 It will make it a little easier to understand what you are trying todo in code. 这将使您更容易理解代码中要执行的操作。

Edit 编辑


Here is an example of using an enum with the above example. 这是在上面的示例中使用enum的示例。 I'm going to use your already existing code as a base. 我将使用您已经存在的代码作为基础。

Create an enum (preferably in a new file). 创建一个枚举(最好在一个新文件中)。

public enum AppType
{
    Normal,
    Expedited
}

Now modify your property to use the enum 现在修改您的属性以使用枚举

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

        OnPropertyChanged( "AppType" );
    }
}

Now you can use my above example, but with an enum: 现在,您可以使用上面的示例,但带有一个枚举:

<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>

The following is nice for having a little more control over what is displayed in the ComboBox . 下面的代码可以更好地控制ComboBox显示的内容。 However you can also have it display every enum value, which is nice because if you add enum values in the future, they will automatically show up in the ComboBox . 但是,您也可以让它显示每个enum值,这很好,因为如果将来添加enum值,它们会自动显示在ComboBox See this question and answer for a way of doing that. 请参阅此问题和答案以了解解决方法。

My advice is to use ValueConverter. 我的建议是使用ValueConverter。 It's more flexable solution than using Tag values and it's looks nice because you are separating conversion logic in its own class. 与使用Tag值相比,它是更灵活的解决方案,并且看起来不错,因为您将转换逻辑分隔在其自己的类中。 Also I noticed that in your data class you declared PropertyChanged event but not implemented INotifyPropertyChanged interface so you can't have two way binding in this case. 我还注意到,在您的数据类中,您声明了PropertyChanged事件,但未实现INotifyPropertyChanged接口,因此在这种情况下,您将无法进行双向绑定。 Full example: 完整示例:

Your data class (with my fixes) 您的数据类(包含我的修正)

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));
    } 
}

Value converter 价值转换器

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 xaml.cs

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

Xaml 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>

Pay attention on this line: xmlns:local="clr-namespace:WpfConvertion" . 请注意以下这一行: xmlns:local =“ clr-namespace:WpfConvertion” You must set your own namespace here instead of my WpfConvertion. 您必须在这里设置自己的名称空间,而不是我的WpfConvertion。

There are several ways to achieve this the simplest could be to add a bind to your AppType with SelectedIndex property of your ComboBox Note that you should add INotifyPropertyChanged to let your binding work 有几种方法可以实现此目的,最简单的方法是使用ComboBox的SelectedIndex属性将绑定添加到您的AppType中。请注意,您应该添加INotifyPropertyChanged来使绑定起作用

and in code behind do the following 并在后面的代码中执行以下操作

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));
        }
    }
}

最简单的方法是,如果您的Normal值为0,而Expedited值为1,则使用SelectedIndex进行绑定。

<ComboBox SelectedIndex="{Binding AppType}" >

You could use a converter, or tags, as the other answers have shown. 您可以使用转换器或标签,如其他答案所示。 But you could also define your item-source as a class rather than rely on hand-waving to link integers to strings. 但是您也可以将item-source定义为类,而不是依靠手工将整数链接到字符串。 So your item source items could be a class like this: 因此,您的商品来源商品可能是这样的类:

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

You can then use SelectedValue and SelectedValuePath binding on your combobox to define what changes in your datacontext, and what property is used in the lookup list. 然后,可以在组合框上使用SelectedValue和SelectedValuePath绑定来定义数据上下文中的哪些更改以及在查找列表中使用的属性。

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

You could also define a Template for your Combobox where you gain more control over how the lookup list of items is displayed. 您还可以为组合框定义一个模板,从中可以更好地控制项目的查找列表的显示方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM