C# WPF - 组合框数据绑定

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21124858/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:31:46  来源:igfitidea点击:

C# WPF - ComboBox DataBinding

c#wpfxamldata-bindingcombobox

提问by user3175176

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,因为它必须将它从字符串(“正常”、“加速”)转换为字节(0、1)并在对象和组合框之间返回。

Thanks for any help in advance!

提前感谢您的任何帮助!

回答by deloreyk

You could do this several ways, however here is a simple solution todo what you have asked. Note, your DataContextwill 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>

SelectedValueis binded to your property, and SelectedValuePathis 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 Enumto represent this data. It will make it a little easier to understand what you are trying todo in code.

这是一个非常简单的解决方案,您可能需要根据需要对其进行更改。此外,我会考虑使用Enum来表示这些数据。这将使您更容易理解您在代码中尝试执行的操作。

Edit

编辑



Here is an example of using an enumwith the above example. I'm going to use your already existing code as a base.

这是将enum与上述示例一起使用的示例。我将使用您现有的代码作为基础。

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. However you can also have it display every enumvalue, which is nice because if you add enumvalues in the future, they will automatically show up in the ComboBox. See this question and answerfor a way of doing that.

以下内容有助于更好地控制ComboBox. 但是,您也可以让它显示每个enum值,这很好,因为如果您enum将来添加值,它们将自动显示在ComboBox. 请参阅此问题和答案以了解这样做的方法。

回答by Deffiss

My advice is to use ValueConverter. It's more flexable solution than using Tagvalues and it's looks nice because you are separating conversion logic in its own class. Also I noticed that in your data class you declared PropertyChangedevent but not implemented INotifyPropertyChanged interface so you can't have two way binding in this case. Full example:

我的建议是使用 ValueConverter。它比使用Tag值更灵活,而且看起来不错,因为您将转换逻辑分离在自己的类中。另外我注意到在你的数据类中你声明了PropertyChanged事件但没有实现 INotifyPropertyChanged 接口,所以在这种情况下你不能有两种方式绑定。完整示例:

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

xml文件

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

Xaml

xml

<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". You must set your own namespace here instead of my WpfConvertion.

注意这一行:xmlns:local="clr-namespace:WpfConvertion"。你必须在这里设置你自己的命名空间而不是我的 WpfConvertion。

回答by Mashton

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

您还可以为您的组合框定义一个模板,您可以在其中更好地控制项目查找列表的显示方式。

回答by BRAHIM Kamel

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

回答by Frank Pfattheicher

The simplest way is, if yout Normal value is 0 and your Expedited value is 1, use SelectedIndex to bind to.

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

<ComboBox SelectedIndex="{Binding AppType}" >

<ComboBox SelectedIndex="{Binding AppType}" >