在WinForm Combobox上使用数据绑定以及用于添加和删除项目的格式

时间:2015-02-26 13:35:33

标签: c# .net winforms 2-way-object-databinding

我在Visual Basic和C#中都在.NET Framework 3.5中维护一些旧的WinForms,但是我很难尝试绑定到POCO数据类。

我得到了这个(使用INotifyPropertyChanged):

public string DisplayUnits
{  
     get { return _displayUnits; }
     set
         { 
             _displayUnits = value;
             NotifyChange("DisplayUnits");
         }
}

public string SetUnit
{
    get { return _setUnit; }
    set
        {
          _setUnit = value;
          NotifyChange("SetUnit");
        }
}

设置SetUnit不是问题,因为我得到了这个:

ComboxBoxUnits.DataBindings.Add("SelectedItem", data, "SetUnit", False, DataSourceUpdateMode.OnPropertyChanged)

这是有效的,因为它是字符串的字符串,但data.DisplayUnits是一个字符串即。 "英寸;脚;码;毫米;厘米; M"目前ComboBox的填充方式如下:

ComboBoxUnits.Items.AddRange(data.DisplayUnits.Split(";"));

此外,用户还可以添加和删除该列表中的项目。因此,当我需要执行Items.Add或Items.Remove时,如何在更新组合框项目列表时将其绑定到DisplayUnits属性并触发更改?

相反,它必须是像WPF中那样的双向数据绑定。当data.DisplayUnits由另一个进程(即:ft2; yard2; cm2; m2)更新时,从它们更改为不同的"产品" (就像第一个产品将测量长度而第二个产品将测量近似区域),我需要更新UI以反映Combox.Items中的这些变化

在MVVM中,我可以尝试使用ITypeConverter(Convert,ConvertBack),但我不认为WinForms支持它;但必须有一种方法可以将Combobox.Items格式化为数据类的POCO属性,并将POCO类转换回Winform的相同内容。

有什么想法吗?

更新:澄清 - 我将其保留在普通旧CLR对象(PO​​CO)中的原因是因为"数据"将用于XML序列化。 XML文件将使用PIC处理器下载到自定义机器。 &#34 ;;"用于解析。因此,DisplayUnit必须采用以下格式" in; ft; yd"。

此外,这将在VS2008中编译,因为我们使用的触摸屏运行的是WinCE 6.5。一半将在C#中,而另一半将在Visual Basic中。

1 个答案:

答案 0 :(得分:0)

我不知道我是否在这里理解你,但是根据我的想法,你需要设置你的ComboBox的DataSource属性。这就是我在Winforms中的表现:

添加一个定义ComboBox的DataSource的类:

class ComboDataSource 
{
    // Display is the property shown as item in your ComboBox (DisplayMember)
    public string Display { get; set; }

    // you could also add a ValueMember ID or something 
}

添加一个方法,将DisplayUnits作为参数并将字符串剪切为字符串数组。浏览字符串并创建并添加ComboDataSource。将列表分配给ComboxBoxUnits.DataSource。定义DisplayMember(当然它是ComboDataSource的Display属性)

private void UpdateDataSource(string data)
{
    var split = data.Split(';');

    List<ComboDataSource> list = new List<ComboDataSource>();
    foreach (var item in split)
        list.Add(new ComboDataSource() { Display = item });

    ComboxBoxUnits.DataSource = list;
    ComboxBoxUnits.DisplayMember = "Display";
}

对于这个例子,我创建了一个包装DisplayUnits和SetUnit(s)属性的类。 (我没有实现SetUnit) 实现INotifyPropertyChanged接口。

class Data : INotifyPropertyChanged
{
    private string _displayUnits;
    public string DisplayUnits
    {
        get { return _displayUnits; }
        set
        {
            _displayUnits = value;
            OnPropertyChanged("DisplayUnits");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

然后,您可以在代码中创建Data对象。像这样......

Data data = new Data();

订阅PropertyChangedEvent ...

data.PropertyChanged +=(sender, args) => UpdateDataSource(data.DisplayUnits); // pass in the DisplayUnits 

设置数据......

data.DisplayUnits = "cm;km;feet;yard";

PropertyChanged事件将触发并更新您的DataSource,以及ComboBox中显示的项目。

希望这会有所帮助......

更新:从ComboBox中删除项目并重新绑定它。 (buttonClick或其他东西)

ComboDataSource selectedItem = comboBox1.SelectedItem as ComboDataSource;
if(selectedItem == null)
    throw new NullReferenceException("selectedItem");

// get the DataSource back from the ComboBox
List<ComboDataSource> dataSource = comboBox1.DataSource as List<ComboDataSource>;
if (dataSource != null)
{
    // remove it from the datasource
    dataSource.Remove(selectedItem);

    // so this is pretty 'straight forward' and certainly not best practice, but we put the datasource back up again the same way we have set it
    string[] comboBoxItems = dataSource.Select(item => item.Display).ToArray();
    // join the string (f.e. 'km;cm;feet') and update it again
    string newDataSource = string.Join(";", comboBoxItems);
    UpdateDataSource(newDataSource);
}