繁体   English   中英

ComboBox 绑定枚举属性不起作用 C# Winforms

[英]ComboBox Binding an enum property is not working C# Winforms

嗨,我在用户控件中有一个函数,它将显示和创建用户控件并根据属性的类型绑定它的值

我能够执行 text 属性,但绑定带有枚举的组合框对我不起作用这里是以下代码

public void DisplayProperties(object obj)
    {
        // get Display Name
        DisplayNameAttribute groupNameAttribute = Attribute.GetCustomAttribute(obj.GetType(), typeof(DisplayNameAttribute)) as DisplayNameAttribute;
        if (groupNameAttribute != null)
        {
            propertyPanel.Controls.Add(DisplayCategory(groupNameAttribute.DisplayName));
        }
        else
        {
            propertyPanel.Controls.Add(DisplayCategory(obj.GetType().Name));
        }

        PropertyInfo[] propInfo = obj.GetType().GetProperties();
        foreach (PropertyInfo property in propInfo)
        {
            BrowsableAttribute attrib = property.GetCustomAttribute(typeof(BrowsableAttribute)) as BrowsableAttribute;
            if(attrib == null || attrib.Browsable == true)
            {
                DisplayNameAttribute propName = Attribute.GetCustomAttribute(property.GetType(), typeof(DisplayNameAttribute)) as DisplayNameAttribute;
                string displayName;
                if (propName != null)
                {
                    displayName = propName.DisplayName;
                }
                else
                {
                    displayName = property.Name;
                }
                object attrs = property.GetCustomAttributes(true);
                DescriptionAttribute propertyDescription = attrs as DescriptionAttribute;
                if (property.PropertyType.IsEnum)
                {
                    ComboBoxProperty comboProperty = new ComboBoxProperty();
                    comboProperty.ComboDisplayName = displayName;
                    comboProperty.propertyComboBox.DataSource = property;
                    comboProperty.propertyComboBox.DataBindings.Add("SelectedValue", obj, displayName);
                    comboProperty.Description = "test";// propertyDescription.Description;
                    propertyPanel.Controls.Add(comboProperty);
                }
                else
                {
                    TextBoxProperty textBoxProperty = new TextBoxProperty();
                    //if (property.PropertyType == typeof(string))
                    //{
                    textBoxProperty.TextDisplayName = displayName;
                    textBoxProperty.valueTb.DataBindings.Add(new Binding("Text", obj, displayName)); //property.GetValue(obj, null).ToString();
                    textBoxProperty.Description = "test";//propertyDescription.Description;
                    textBoxProperty.Top = _PropertyPosition;
                    _PropertyPosition += textBoxProperty.Height;
                    propertyPanel.Controls.Add(textBoxProperty);
                    //}
                }
            }
        }
    }

这个函数是从一个表单中调用的

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
       TestObject textObject = new TestObject();
        textObject.TestString = "testing";
        textObject.TestEnum = TestObject.MyEnum.A;
        propertyGrid1.DisplayProperties(textObject);

    }


}
public class TestObject
{
    public enum MyEnum 
    {
        A,
        B
    }
    public string TestString { get; set; }
    //public int TestInteger { get; set; }
    //public double TestDouble { get; set; }
    public MyEnum TestEnum {get; set;}

}

我希望组合框包含所有枚举值和要显示的选定值。 让我知道如何解决我的问题

编辑

我做了一些阅读,我能够让枚举工作,但数据绑定不起作用我确定这是因为 ValueMember 如果不是来自 DataBidning 本身,这里是我更新的代码,来自包含 2 个用户控件类的 UserControl 类的代码一个用于组合框,第二个用于文本框

public partial class PropertyGrid : TouchObjectListBox
{
     int _PropertyPosition = 0;
    public PropertyGrid()
    {
        InitializeComponent();

    }

    public void DisplayProperties(object obj)
    {
        // get Display Name
        DisplayNameAttribute groupNameAttribute = Attribute.GetCustomAttribute(obj.GetType(), typeof(DisplayNameAttribute)) as DisplayNameAttribute;
        if (groupNameAttribute != null)
        {
            propertyPanel.Controls.Add(DisplayCategory(groupNameAttribute.DisplayName));
        }
        else
        {
            propertyPanel.Controls.Add(DisplayCategory(obj.GetType().Name));
        }

        PropertyInfo[] propInfo = obj.GetType().GetProperties();
        foreach (PropertyInfo property in propInfo)
        {
            BrowsableAttribute attrib = property.GetCustomAttribute(typeof(BrowsableAttribute)) as BrowsableAttribute;
            if(attrib == null || attrib.Browsable == true)
            {
                DisplayNameAttribute propName = Attribute.GetCustomAttribute(property.GetType(), typeof(DisplayNameAttribute)) as DisplayNameAttribute;
                string displayName;
                if (propName != null)
                {
                    displayName = propName.DisplayName;
                }
                else
                {
                    displayName = property.Name;
                }
                object attrs = property.GetCustomAttributes(true);
                DescriptionAttribute propertyDescription = attrs as DescriptionAttribute;
                if (property.PropertyType.IsEnum)
                {
                    ComboBoxProperty comboProperty = new ComboBoxProperty();
                    comboProperty.ComboDisplayName = displayName;
                    comboProperty.propertyComboBox.ValueMember = displayName;
                    comboProperty.propertyComboBox.DataSource = Enum.GetNames(property.PropertyType);
                    comboProperty.propertyComboBox.DataBindings.Add(new Binding("SelectedValue",obj, displayName));
                    comboProperty.Description = "test";
                    comboProperty.Top = _PropertyPosition;
                    _PropertyPosition += comboProperty.Height;
                    propertyPanel.Controls.Add(comboProperty);
                }
                else
                {
                    TextBoxProperty textBoxProperty = new TextBoxProperty();
                    //if (property.PropertyType == typeof(string))
                    //{
                    textBoxProperty.TextDisplayName = displayName;
                    textBoxProperty.valueTb.DataBindings.Add(new Binding("Text", obj, displayName));
                    textBoxProperty.Description = "test";// propertyDescription.Description;
                    textBoxProperty.Top = _PropertyPosition;
                    _PropertyPosition += textBoxProperty.Height;
                    propertyPanel.Controls.Add(textBoxProperty);
                    //}
                }
            }
        }
    }

    private Label DisplayCategory(string groupName)
    {
        Label groupLabel = new Label();
        groupLabel.ForeColor = SystemPens.ControlLightLight.Color;
        groupLabel.BackColor = SystemPens.ControlDark.Color;
        groupLabel.TextAlign = ContentAlignment.MiddleLeft;
        groupLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        groupLabel.Text = groupName;
        groupLabel.Width = propertyPanel.Width;
        groupLabel.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
        groupLabel.Top = _PropertyPosition;
        _PropertyPosition += groupLabel.Height;
        return groupLabel;
    }
}

这个调用 UserControl 的 Form

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
      List<TestObject> testObject = new List<TestObject>();

      testObject.Add(new TestObject() { TestString = "testing1", TestEnum = TestObject.MyEnum.A });
      testObject.Add(new TestObject() { TestString = "testing2", TestEnum = TestObject.MyEnum.B });
        foreach(var obj in testObject)
        {
            propertyGrid1.DisplayProperties(obj);
        }

    }


}
public class TestObject
{
    [Browsable(true)]
    //[CategoryOrder("Beam Parameters", 2)]
    [DisplayName("Test String")]
    [Description("testString description")]
    public string TestString { get; set; }
    //public int TestInteger { get; set; }
    //public double TestDouble { get; set; }
    public enum MyEnum
    {
        A,
        B
    }
    private MyEnum m_cycleMode = MyEnum.A;
    [Browsable(true)]
    [DisplayName("Cycle Mode")]
    [Description("Specifies how this process step is processed")]
    public MyEnum TestEnum { get { return m_cycleMode; } set { m_cycleMode = value; } }


}

问题是当我加载应用程序组合框时没有选择初始值,当我更改它时,它将调用属性 MyEnum 并获取结果但不显示所选值,该值再次变为空白

有任何想法吗

我不确定您要做什么,但是,当我理解得很好时,您想使用枚举的值绑定到另一个控件的文本吗?

在您的代码中,将绑定的DataSource设置为体现的属性。 这完全没有必要,因为您可以指定要绑定到的属性的名称。

您需要执行的第二步是将枚举的值添加到您创建的ComboBox中。 否则,您将没有任何物品。 以下显示了如何执行此操作的示例:

foreach (ETestEnum value in Enum.GetValues(typeof(ETestEnum)))
{
    this.combo.Items.Add(new ComboBoxItem { Content = value });
}

ComboBoxItem只是一个示例,也许不是您想要的。 相反,您也可以使用具有两个属性的自己的类,这些属性分别是DescriptionValue或类似的属性。 然后可以使用ComboBox上的SelectedValuePathDisplayMemberPath对其进行配置。

您需要将属性的值分配给itemSource,而不是属性本身:

comboProperty.propertyComboBox.DataSource = property;

将以下功能添加到用户控件:

private void SetBindingForComboBoxWithEnumItems(ComboBox cmb,Type enumType)
{
  List<KeyValuePair<object, string>> values = new List<KeyValuePair<object,string>>();
  List<Tuple<object, string, int>> enumList=Enum.GetValues(enumType).Cast<object>().Select(x=>Tuple.Create(x, x.ToString(), (int)x)).ToList();
  foreach (var idx in enumList)
  {
     values.Add(new KeyValuePair<object, string>(idx.Item1, idx.Item2));
  }
  cmb.ItemsSource = values;
  cmb.DisplayMemberPath = "Value";
  cmb.SelectedValuePath = "Key";
}

将上面的代码更改为:

if (property.PropertyType.IsEnum)
{
   ComboBox cmb=new ComboBox();
   Binding myBinding = new Binding();
   myBinding.Path = new PropertyPath(property.Name);
   myBinding.Mode = BindingMode.TwoWay;
   myBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
   BindingOperations.SetBinding(cmb, ComboBox.SelectedValueProperty, myBinding);
   SetBindingForComboBoxWithEnumItems(cmb,obj.GetType().GetProperty(property.Name).GetType());
   propertyPanel.Controls.Add(cmb);
}

好的,这是一个对我完全有用的示例。 有一个带有组合框和按钮的窗口。

<Window x:Class="WPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Name="window">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <ComboBox x:Name="combobox" Grid.Column="0" Grid.Row="0"/>
        <Button Content="Click" Click="Button_Click" Grid.Row="1"/>
    </Grid>
</Window>

以及后面的代码:

public enum ETestEnum
{
    Value1,
    Value2,
}

public partial class MainWindow : Window
{

    public ETestEnum EnumValue
    {
        get { return (ETestEnum)GetValue(EnumValueProperty); }
        set { SetValue(EnumValueProperty, value); }
    }

    public static readonly DependencyProperty EnumValueProperty =
        DependencyProperty.Register("EnumValue", typeof(ETestEnum), typeof(MainWindow), new PropertyMetadata(ETestEnum.Value1));


    public MainWindow()
    {
        InitializeComponent();

        foreach (ETestEnum value in Enum.GetValues(typeof(ETestEnum)))
        {
            this.combobox.Items.Add(value);
        }            
        Binding binding = new Binding();
        binding.Source = this;
        binding.Path = new PropertyPath("EnumValue");
        this.combobox.SetBinding(ComboBox.SelectedValueProperty, binding);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        EnumValue = EnumValue == ETestEnum.Value1 ? ETestEnum.Value2 : ETestEnum.Value1;
    }
}

暂无
暂无

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

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