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