5

次のコードでは、TextプロパティはDateTimeソースプロパティにバインドされていますが、ValueConverterを記述しなくても、WPFがテキストをDateTimeに自動的に変換しているように見えることに気付きました。誰かがこれがどのように行われるかについていくつかの光を当てることができますか

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:WpfApplication1="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525"
        >    
    <StackPanel>
        <DatePicker Height="25" Name="datePicker1" Width="213" Text="{Binding Path=DueDate,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
    </StackPanel>
</Window>
public class P
    {
        private DateTime? dueDate = DateTime.Now;
        public DateTime? DueDate
        {
            get { return dueDate; }
            set 
            { 
                dueDate = value;
            }
        }
    }

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            P p = new P();
            this.DataContext = p;
        }
    }
4

3 に答える 3

5

DateTimeTypeConverterBase Class Libraryを使用しています(編集: TypeConverterを使用することもできましたが、@DeviantSeevの回答からは使用しなかったようです)。

あなたが話している「デフォルト」のコンバーターは実際にはTypeConverters( MSDN ) であり、v2.0 から .NET Framework の一部であり、基本クラス ライブラリ全体で使用されています。WPF の TypeConverters のもう 1 つの例は、ThicknessTypeConverterfor PaddingMargin、およびBorderThicknessプロパティです。コンマ区切りの文字列をThicknessオブジェクトに変換します。

それらをさらに理解したい場合は、利用可能な記事たくさんあります

TypeConverterクラスの実装とプロパティ/タイプのマークアップには、2 つの部分がありますTypeConverterAttribute

たとえば、最近、次のように設定したい を必要とするカスタム コントロールがありました char[]Xaml

<AutoCompleteTextBox MultiInputDelimiters=",;. " />

使用法

[TypeConverter(typeof(CharArrayTypeConverter))]
public char[] MultiInputDelimiters
{
      get { return (char[])GetValue(MultiInputDelimitersProperty); }
      set { SetValue(MultiInputDelimitersProperty, value); }
}

実装

public class CharArrayTypeConverter : TypeConverter
{

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return (Type.GetTypeCode(sourceType) == TypeCode.String);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        if (value is string)
            return ((string)value).ToCharArray();

        return value;
    }

}

いつ使用するのTypeConverterですか?

TypeDescriptorsを使用してプロパティをマークアップできる必要があるため、カスタム コントロールを作成している場合にのみ使用できますTypeDescriptorAttribute。またTypeConverter、上記の例のように文字列があり、変換が必要な場合のように、変換がかなり単純な場合、char[]または変換元のフォーマットが複数ある場合にのみ使用します。

IValueConverterデータまたはパラメーターを渡すことによって値を変換する方法について、より柔軟な方法が必要な場合に書き込みます。たとえば、WPF の非常に一般的なアクションは、aboolVisibility;に変換することです。このような変換 ( VisibleHiddenCollapsed) からの 3 つの可能な出力があり、2 つの入力 ( truefalse) だけでは、これを a で決定するのは困難TypeConverterです。

私のアプリケーションでは、この 2 つの入力から 3 つの出力の問題を達成するためにBoolToVisibilityConverterTrueValueFalseValueプロパティを使用して 1 つを記述し、それを global で 3 回インスタンス化しましたResourceDictionary明日の朝にコード サンプルを投稿しますが、今は目の前にありません。.

[ValueConversion(typeof(bool), typeof(Visibility))]
public class BooleanToVisibilityConverter : IValueConverter
{
    public Visibility FalseCondition { get; set; }
    public Visibility TrueCondition { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return ((bool)value) ? TrueCondition : FalseCondition;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if ((bool)value)
            return TrueCondition;

        return FalseCondition;
    }
}

<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" FalseCondition="Collapsed" TrueCondition="Visible"/>
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityCollapsedConverter" FalseCondition="Visible" TrueCondition="Collapsed"/>
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityHiddenConverter" FalseCondition="Visible" TrueCondition="Hidden"/>
<converters:BooleanToVisibilityConverter x:Key="BoolToVisibilityHiddenWhenFalseConverter" FalseCondition="Hidden" TrueCondition="Visible"/>
于 2012-03-08T21:57:35.657 に答える
1

DatePicker は、.NET 4 で標準コントロールとして追加される前は、最初は WPF ツールキットの一部であったカスタム コントロールです。

コントロールのソース コード リポジトリにアクセスして、テキストを現在の状態に変換する正確なソース コードを見つけました。

#region Text

    /// <summary>
    /// Gets or sets the text that is displayed by the DatePicker.
    /// </summary>
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    /// <summary>
    /// Identifies the Text dependency property.
    /// </summary>
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register(
        "Text",
        typeof(string),
        typeof(DatePicker),
        new FrameworkPropertyMetadata(string.Empty, OnTextChanged, OnCoerceText));

    /// <summary>
    /// TextProperty property changed handler.
    /// </summary>
    /// <param name="d">DatePicker that changed its Text.</param>
    /// <param name="e">DependencyPropertyChangedEventArgs.</param>
    private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DatePicker dp = d as DatePicker;
        Debug.Assert(dp != null);

        if (!dp.IsHandlerSuspended(DatePicker.TextProperty))
        {
            string newValue = e.NewValue as string;

            if (newValue != null)
            {
                if (dp._textBox != null)
                {
                    dp._textBox.Text = newValue;
                }
                else
                {
                    dp._defaultText = newValue;
                }

                dp.SetSelectedDate();
            }
            else
            {
                dp.SetValueNoCallback(DatePicker.SelectedDateProperty, null);
            }
        }
    }

    private static object OnCoerceText(DependencyObject dObject, object baseValue)
    {
        DatePicker dp = (DatePicker)dObject;
        if (dp._shouldCoerceText)
        {
            dp._shouldCoerceText = false;
            return dp._coercedTextValue;
        }

        return baseValue;
    }

    /// <summary>
    /// Sets the local Text property without breaking bindings
    /// </summary>
    /// <param name="value"></param>
    private void SetTextInternal(string value)
    {
        if (BindingOperations.GetBindingExpressionBase(this, DatePicker.TextProperty) != null)
        {
            Text = value;
        }
        else
        {
            _shouldCoerceText = true;
            _coercedTextValue = value;
            CoerceValue(TextProperty);
        }
    }

    #endregion Text
于 2012-03-08T21:17:30.580 に答える
0

ほとんどの場合、WPFがToString()を呼び出していると思いますが、日付ピッカーのコードを見ると、重要な行は次のとおりです。

(string)GetValue(TextProperty)

「Text」プロパティに割り当てた値を文字列にキャストすることに注意してください。重要なのは、BooleanToVisibilityConverterなどの従来の意味でのデフォルトのコンバーターがないということです。

于 2012-03-08T21:22:22.557 に答える