2015-07-27 2 views
0

Я борюсь за разработку компонента в WPF. Вот моя проблема:True False Null ComboBox

У меня есть bool? свойство, которое я хочу привязать к SelectedValue ComboBox. My ComboBox должен иметь 3 варианта: «Да» (bool = true), «Нет» (bool = false), «» (bool == null).

Я создал UserControl, который наследуется от ComboBox. В конструкторе я заполнил ItemCollection необходимыми значениями («Да»/«Нет»/«»).

CodeBehind:

public class YesNoNullComboBox : RadComboBox 
{ 
    public YesNoNullComboBox() 
    { 
     this.Items.Add("Yes"); 
     this.Items.Add("No"); 
     this.Items.Add(string.Empty); 
    } 
} 

XAML:

<utils:YesNoNullComboBox SelectedValue="{Binding BoolValue}" /> 

мне удалось получить что-то, работающий так, как я хочу, но для этого я должен был использовать конвертер. Таким образом, у меня есть UserControl и конвертер для добавления в мой XAML.

Я думал о том, чтобы установить UserControl на использование конвертера по умолчанию, но я не понял, как это сделать. Возможно ли это? Или есть лучший способ?

+0

«UserControl, который наследуется от ComboBox» - пользовательские элементы управления предназначены для * агрегации * других элементов управления вместо их наследования. – Dennis

+0

Я не понял, что вы подразумеваете под третьим абзацем –

+0

Я только что редактировал мой вопрос, чтобы сделать его более ясным – MxFragz

ответ

2

Вы должны указать конвертер в своей декларации привязки, но вы можете сделать это внутри.
Я набросал это:

1) вспомогательный класс для хранения строковых значений для работы в ComboBox и преобразователя:

public static class ThreeStateComboBoxItemsSource 
{ 
    public const string None = "(none)"; 
    public const string Yes = "Yes"; 
    public const string No = "No"; 

    public static readonly string[] ItemsSource = new[] 
    { 
     None, 
     Yes, 
     No 
    }; 
} 

2) Преобразователь:

[ValueConversion(typeof(bool?), typeof(string))] 
public sealed class NullableBoolToStringConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) 
      return ThreeStateComboBoxItemsSource.None; 

     return (bool)value ? ThreeStateComboBoxItemsSource.Yes : ThreeStateComboBoxItemsSource.No; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     switch ((string)value) 
     { 
      case ThreeStateComboBoxItemsSource.Yes: 
       return true; 
      case ThreeStateComboBoxItemsSource.No: 
       return false; 
      default: 
       return null; 
     } 
    } 
} 

3) контроль пользователя , Я не хочу, чтобы пользователь мог переопределить поведение CombeBox (например, установить другой ItemsSource), я обернутый CB в UserControl, вместо наследования:

XAML:

<UserControl x:Class="WpfApplication4.ThreeStateComboBox" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:WpfApplication4" 
      mc:Ignorable="d"> 

    <UserControl.Resources> 
     <local:NullableBoolToStringConverter x:Key="NullableBoolToStringConverterKey"/> 
    </UserControl.Resources> 

    <ComboBox x:Name="InnerComboBox" 
       SelectedItem="{Binding Value, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Converter={StaticResource NullableBoolToStringConverterKey}}" 
       ItemsSource="{x:Static local:ThreeStateComboBoxItemsSource.ItemsSource}"/> 
</UserControl> 

code- позади:

public partial class ThreeStateComboBox : UserControl 
{ 
    public ThreeStateComboBox() 
    { 
     InitializeComponent(); 
    } 

    public bool? Value 
    { 
     get { return (bool?)GetValue(ValueProperty); } 
     set { SetValue(ValueProperty, value); } 
    } 

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
     "Value", 
     typeof(bool?), 
     typeof(ThreeStateComboBox), 
     new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); 
} 

4) образец Использование:

<local:ThreeStateComboBox Value="{Binding MyProperty1}"/> 

Поскольку конвертер используется внутри пользовательского элемента управления, вам не нужно использовать его в другом месте, просто привяжите bool/bool? к Value.

+0

Это именно то, что я искал. Большое спасибо Деннис. – MxFragz

3

Цель ValueConverters - связать 2 свойства, которые имеют несовместимые типы. Здесь вы хотите, чтобы boolean стало строкой. Неявное преобразование в строку дает вам «true» или «false», но не строки, которые вы хотите.

На мой взгляд ValueConverters - лучшее и самое простое решение вашей ситуации.

+0

Это была моя первая догадка, и я заставил ее работать таким образом. Что меня беспокоит, так это то, что мой пользовательский UserControl реализован в двух разных частях. Один из них - UserControl, другой - Конвертер. Есть ли способ собрать эти части вместе? Таким образом, мне не нужно будет добавлять UserControl AND the Converter в XAML, каждый раз, когда я хочу его использовать. – MxFragz

+2

Почему бы и нет? Это просто зависит от вашего пользовательского контроля, и нечего стыдиться этого. В любом случае, я не вижу другого чистого решения. – Paradise228

Смежные вопросы