2009-10-10 63 views
5

所以我可能會推動邊界只是有點...WPF組合框/列表框與多重選擇基於枚舉與旗

基本上我有以下枚舉,在C#代碼中聲明:

[Flags] 
public enum FlaggedEnum : int 
{ 
    Option1 = 1, 
    Option2 = 2, 
    Option3 = 4, 
    Option4 = 8, 
    ... 
    Option16 = 32768, 
    None = 0 
} 

此枚舉是我成功綁定到DataGrid對象的對象的成員。成功意味着我已經成功綁定了所有其他字段。 :)

我想在這裏實現的是一個控件,其中所有適當的選項被檢查,行爲和行爲像一個組合框/列表框。所以你點擊該字段,彈出一個下拉菜單,可以「檢查」任何需要的選項。

控件還必須能夠從枚舉中讀取並寫入一個枚舉。

我是WPF新手,所以我不知道從哪裏開始創建一個組合框和綁定到列......任何幫助將不勝感激!

回答

4

我有一種方法可能工作。我不記得這一點 - 我發現這種方法在網上,忘了保存地址。

在我的項目中,我需要將一些複選框綁定到標誌枚舉。爲了幫助,我找到了一個簡單的值轉換器來實現雙向綁定。它不是通用的,轉換器的單個實例一次只能用於一個目標(意味着一個值的實例及其複選框組)。轉換器使用存儲的對該值的引用作爲轉換的方式,所以如果嘗試在單獨的對象實例之間重用它,它將不起作用。這就是說,這是我用於這種事情的唯一用途,它像一個魅力。

轉換器:

/// <summary> 
/// Provides for two way binding between a TestErrors Flag Enum property and a boolean value. 
/// TODO: make this more generic and add it to the converter dictionary if possible 
/// </summary> 
public class TestActionFlagValueConverter : IValueConverter { 
    private TestErrors target; 

    public TestActionFlagValueConverter() { 

    } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { 
     TestErrors mask = (TestErrors)parameter; 
     this.target = (TestErrors)value; 
     return ((mask & this.target) != 0); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { 
     this.target ^= (TestErrors)parameter; 
     return this.target; 
    } 
} 

在XAML它正是如此使用:

<StackPanel.Resources> 
    <local:TestActionFlagValueConverter x:Key="TestActionFlagValueConverter"/> 
</StackPanel.Resources> 

<CheckBox IsChecked="{Binding Errors, Converter={StaticResource TestActionFlagValueConverter}, ConverterParameter={x:Static local:TestErrors.PowerFailure}... 
<CheckBox IsChecked="{Binding Errors, Converter={StaticResource TestActionFlagValueConverter}, ConverterParameter={x:Static local:TestErrors.OpenCondition}... 

你的情況,你可能把這個到您的DATACELL模板(雖然很明顯,你可能更喜歡使用ComboBox ragther請確保轉換器靠近複選框組容器,以確保它們具有自己的轉換器實例。

編輯:

在這裏,我做了一個小測試項目來演示如何在一個帶有datagrid的組合框中使用它,它基於默認的WPF應用程序 - 只需確保引用WPF工具包。

這裏是Window1.xaml文件:

<Window 
    x:Class="FlagEnumTest.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:Controls="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit" 
    xmlns:FlagEnumTest="clr-namespace:FlagEnumTest" 
    Title="Window1" Height="300" Width="300"> 

    <Window.Resources> 
     <x:Array Type="{x:Type FlagEnumTest:TestObject}" x:Key="TestArray"> 
      <FlagEnumTest:TestObject Errors="OpenCondition" /> 
      <FlagEnumTest:TestObject /> 
     </x:Array> 
    </Window.Resources> 

    <StackPanel> 

     <Controls:DataGrid ItemsSource="{Binding Source={StaticResource TestArray}}"> 
      <Controls:DataGrid.Columns> 
       <Controls:DataGridTemplateColumn Header="Errors"> 
        <Controls:DataGridTemplateColumn.CellTemplate> 
         <DataTemplate> 
          <ComboBox> 
           <ComboBox.Resources> 
            <FlagEnumTest:TestErrorConverter x:Key="ErrorConverter" /> 
           </ComboBox.Resources> 
           <CheckBox Content="PowerFailure" IsChecked="{Binding Path=Errors, Converter={StaticResource ErrorConverter}, ConverterParameter={x:Static FlagEnumTest:TestErrors.PowerFailure}}" /> 
           <CheckBox Content="OpenCondition" IsChecked="{Binding Path=Errors, Converter={StaticResource ErrorConverter}, ConverterParameter={x:Static FlagEnumTest:TestErrors.OpenCondition}}" /> 
          </ComboBox> 
         </DataTemplate> 
        </Controls:DataGridTemplateColumn.CellTemplate> 
       </Controls:DataGridTemplateColumn> 
      </Controls:DataGrid.Columns> 
     </Controls:DataGrid> 

    </StackPanel> 
</Window> 

這裏是Window1.xaml.cs文件的代碼隱藏。

using System; 
using System.Globalization; 
using System.Windows; 
using System.Windows.Data; 

namespace FlagEnumTest { 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window { 
     public Window1() { 
      InitializeComponent(); 
     } 
    } 

    [Flags] 
    public enum TestErrors { 
     NoError = 0x0, 
     PowerFailure = 0x1, 
     OpenCondition = 0x2, 
    } 

    public class TestObject { 
     public TestErrors Errors { get; set; } 
    } 

    /// <summary> 
    /// Provides for two way binding between a TestErrors Flag Enum property and a boolean value. 
    /// TODO: make this more generic and add it to the converter dictionary if possible 
    /// </summary> 
    public class TestErrorConverter : IValueConverter { 
     private TestErrors target; 

     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { 
      TestErrors mask = (TestErrors)parameter; 
      this.target = (TestErrors)value; 
      return ((mask & this.target) != 0); 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { 
      this.target ^= (TestErrors)parameter; 
      return this.target; 
     } 
    } 

} 

默認情況下,DataGrid中會創建自己的列代表以及我的授權模板之一,所以你可以看到文本的表示,以及對應的複選框之一。標誌枚舉混淆了默認的文本表示,但仍然可以看到綁定工作正常(同時選中,然後取消選中上次檢查的字符串值 - 字符串值更改爲另一個,而不是0)。

+0

乾杯,看起來像它會完美!我會繼續嘗試並將其實施到我的應用程序中。 – sohum 2009-10-10 20:48:51

+0

葉戈爾,我能夠完美地工作。我想知道是否可以在複選框狀態發生變化時通知DataGrid某行已被修改?現在,我依靠綁定數據上的IEditableInterface實現將更新寫入後端數據庫。但是,編輯複選框不會觸發此行爲。 – sohum 2009-10-10 21:20:04

+1

另外,是否可以更改組合框中顯示的值?我注意到屬性SelectionBoxItem,但它看起來是隻讀的。 – sohum 2009-10-10 21:35:54