2010-11-29 3 views
20

WPF 데이터 바인딩 : XAML을 사용하여 열거 형을 콤보 상자에 바인딩하는 방법은 무엇입니까?

public class AccountDetail 
{ 
    public DetailScope Scope 
    { 
     get { return scope; } 
     set { scope = value; } 
    } 

    public string Value 
    { 
     get { return this.value; } 
     set { this.value = value; } 
    } 

    private DetailScope scope; 
    private string value; 

    public AccountDetail(DetailScope scope, string value) 
    { 
     this.scope = scope; 
     this.value = value; 
    } 
} 

및 enum :

마지막으로 xxx 파일이 있습니다.

<Window x:Class="Gui.Wpf.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Test" 
    SizeToContent="WidthAndHeight"> 

    <Grid> 
     <ComboBox 
      Name="ScopeComboBox" 
      Width="120" 
      Height="23" 
      Margin="12" /> 
    </Grid> 
</Window> 

두 가지를하고 싶습니다.

  1. DetailsScope 열거 형 값을 콤보 상자 값에 데이터 바인딩합니다. 마지막 열거 형 값이 Other detail 대신 공백 문자와 작은 문자 'd'대신 OtherDetail가 될 것이기 때문에 가 열거 형 값을 직접 바인드하기를 원하지 않습니다.
  2. 콤보 상자에서 선택된 값을 AccountDetail 객체의 인스턴스에 지정된 값으로 데이터 바인딩하려고합니다.

나 좀 도와 줄래? 감사.

업데이트 :이 게시물 http://blogs.msdn.com/b/wpfsdk/archive/2007/02/22/displaying-enum-values-using-data-binding.aspx를 발견했습니다. 나는 비슷한 것을 필요로한다.

답변

37

이 할 수있는 아주 쉬운 방법은 ObjectDataProvider

<ObjectDataProvider MethodName="GetValues" 
        ObjectType="{x:Type sys:Enum}" 
        x:Key="DetailScopeDataProvider"> 
    <ObjectDataProvider.MethodParameters> 
     <x:Type TypeName="local:DetailScope" /> 
    </ObjectDataProvider.MethodParameters> 
</ObjectDataProvider> 

를 사용하여 콤보 상자의 ItemsSource, 범위 속성에 바인딩의 selectedItem으로 ObjectDataProvider를 사용하고 적용하는 것입니다 각 ComboBoxItem의 디스플레이 용 변환기

<ComboBox Name="ScopeComboBox" 
      ItemsSource="{Binding Source={StaticResource DetailScopeDataProvider}}" 
      SelectedItem="{Binding Scope}" 
      Width="120" 
      Height="23" 
      Margin="12"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Converter={StaticResource CamelCaseConverter}}"/> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

그리고 변환기에서 this 질문에있는 CamelCase 문자열 분리기 용 Regex를 사용할 수 있습니다. 가장 진보 된 버전을 사용했지만 아마도 더 간단한 버전을 사용할 수 있습니다. OtherDetail + 정규식 = 기타 정보. 반환 값을 더 낮추고 첫 번째 문자 대문자로 문자열을 반환하면 예상 결과가 나타납니다.

public class CamelCaseConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     string enumString = value.ToString(); 
     string camelCaseString = Regex.Replace(enumString, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1 ").ToLower(); 
     return char.ToUpper(camelCaseString[0]) + camelCaseString.Substring(1); 
    } 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return value; 
    } 
} 
+0

끝내 주네! 고마워, Meleak – Boris

2

다음은 솔루션입니다. 모든 가능성을 포함하는 속성 (목록)을 만들고 해당 속성에 ComboBox를 바인딩합니다. XAML에서

:

<ComboBox 
    Name="ScopeComboBox" 
    Width="120" 
    Height="23" 
    Margin="12" 
    ItemsSource="{Binding Path=AccountDetailsProperty}" 
    DisplayMemberPath="Value"/> 

그리고 뒤에있는 코드 :

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     AccountDetailsProperty = new List<AccountDetail>() 
     { 
      new AccountDetail(DetailScope.Business, "Business"), 
      new AccountDetail(DetailScope.OtherDetail, "Other details"), 
      new AccountDetail(DetailScope.Private, "Private"), 
     }; 

     InitializeComponent(); 
     this.DataContext = this; 
    } 

    public List<AccountDetail> AccountDetailsProperty { get; set; } 
} 
+0

Nicolas, 답장을 보내 주셔서 감사합니다. 더 많은 XAML 지향적 인 솔루션을 찾고 있습니다. http://blogs.msdn.com/b/wpfsdk/archive/2007/02/22/displaying-enum-values-using-data-binding.aspx – Boris

11

난 항상 다음대로 수행 한 방법. 이 솔루션의 장점은 완전히 일반적인 것이므로 모든 열거 유형에 다시 사용할 수 있다는 것입니다.

1) 열거 형을 정의 할 때 약간의 정보를 제공하기 위해 사용자 정의 속성을 사용하십시오. 이 예제에서는 Browsable (false)을 사용하여이 열거자가 내부적임을 나타내므로이 옵션을 콤보 상자에서보고 싶지 않습니다. 설명 ("")을 사용하면 열거 형의 표시 이름을 지정할 수 있습니다.

public enum MyEnumerationTypeEnum 
    { 
    [Browsable(false)] 
    Undefined, 
    [Description("Item 1")] 
    Item1, 
    [Description("Item 2")] 
    Item2, 
    Item3 
    } 

2) EnumerationManager를 호출 한 클래스를 정의하십시오. 이 클래스는 열거 형을 분석하고 값 목록을 생성하는 제네릭 클래스입니다. 열거자가 Browsable을 false로 설정하면 건너 뜁니다. 설명 속성이 있으면 설명 문자열을 표시 이름으로 사용합니다. 설명이 없으면 열거 자의 기본 문자열 만 표시됩니다.당신의 XAML에서

public class EnumerationManager 
    { 
    public static Array GetValues(Type enumeration) 
    { 
     Array wArray = Enum.GetValues(enumeration); 
     ArrayList wFinalArray = new ArrayList(); 
     foreach(Enum wValue in wArray) 
     { 
     FieldInfo fi = enumeration.GetField(wValue.ToString()); 
     if(null != fi) 
     { 
      BrowsableAttribute[] wBrowsableAttributes = fi.GetCustomAttributes(typeof(BrowsableAttribute),true) as BrowsableAttribute[]; 
      if(wBrowsableAttributes.Length > 0) 
      { 
      // If the Browsable attribute is false 
      if(wBrowsableAttributes[0].Browsable == false) 
      { 
       // Do not add the enumeration to the list. 
       continue; 
      }   
      } 

      DescriptionAttribute[] wDescriptions = fi.GetCustomAttributes(typeof(DescriptionAttribute),true) as DescriptionAttribute[]; 
     if(wDescriptions.Length > 0) 
     { 
     wFinalArray.Add(wDescriptions[0].Description); 
     } 
     else 
     wFinalArray.Add(wValue); 
     } 
     } 

     return wFinalArray.ToArray(); 
    } 
    } 

3) ResourceDictionary에에 섹션을 추가

<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type l:EnumerationManager}" x:Key="OutputListForMyComboBox"> 
     <ObjectDataProvider.MethodParameters> 
      <x:Type TypeName="l:MyEnumerationTypeEnum" /> 
     </ObjectDataProvider.MethodParameters> 
    </ObjectDataProvider> 

4) 지금은 단지 우리가 단지 리소스 사전에 정의 된이 키에 콤보 상자의 ItemsSource 바인딩

<ComboBox Name="comboBox2" 
      ItemsSource="{Binding Source={StaticResource OutputListForMyComboBox}}" /> 

위의 열거 형을 사용하여이 코드를 시도하면 콤보 상자에 다음과 같은 항목이 표시됩니다.

Item 1 
Item 2 
Item3 

희망이 도움이됩니다.

EDITS : LocalizableDescriptionAttribute의 구현을 추가하고 그 대신 사용하고있는 설명 특성이 완벽 할 경우.

+0

리즈, 답장을 보내 주셔서 감사합니다. – Boris

+0

이것은 훌륭한 방법입니다. – gakera

+0

SelectedItem을 뷰 모델에 다시 바인딩하는 가장 좋은 방법은 무엇입니까? viewmodel에서 같은 유형의 열거 형에 직접 바인딩하려고하지만 컨트롤에서 보낸 문자열로 설명을 가져 와서 구문 분석합니다 (특히 현지화 된 경우). – gakera

0

나는 값 변환기를 사용하여이 변환기를 사용하여 직접 바인드 할 수 있습니다. 변환 구현을 변경하여 사람이 읽을 수있는 "열거 형"열거 형 표현 (예 : 대문자로 된 분할)을 만들 수 있습니다.

이 방법에 대한 전체 기사는 here입니다.

public class MyEnumToStringConverter : IValueConverter 
    { 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return value.ToString(); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return (MyEnum) Enum.Parse(typeof (MyEnum), value.ToString(), true); 
    } 
    } 

+0

변환기는 좋은 아이디어입니다. 바인딩은 어떻게해야합니까? – Boris

+0

@ 보리스 : 위에 링크 된 기사에 자세한 내용이 있습니다 – BrokenGlass

관련 문제