2017-02-07 16 views
1

コンボボックスを含むカスタムユーザーコントロールがあります。私は、ComboBoxWidth依存プロパティを追加して、開発者が望むなら幅を設定できるようにしました。スタイル・セッターを使用して、これらのコンボ・ボックスの幅を、サイズの一貫性のために別のユーザー・コントロールの同じ値に設定したいとします。しかし、それは動作していません。各コントロールでサイズを個別に設定すると機能します。スタイル・セッターでサイズが指定されると、それは無視されます。プロパティの文字列を "ComboBoxWidth"から "Width"に変更すると、すべてのコントロールの幅全体が変更されます。スタイルの書式が正しいように見えます。何か不足していますか?私自身のカスタム依存プロパティーにスタイルを適用しようとしたのはこれが初めてです。WPFスタイル設定が機能しない

注:AngleUserControlは、一般的なユーザーコントロール(コードで作成されたxamlコントロールは含まない)に基づいています。 ComboBoxWidthプロバティはジェネリックベースクラスにあります。それが何かと関係があるかどうかは分かりません。

スタイルコード(ユーザーコントロールにいくつかのAngleUserControlコントロールを含む):

<UserControl.Resources> 
    <Style TargetType="wpfControls:AngleUserControl"> 
     <Setter Property="ComboBoxWidth" Value="400"/> 
    </Style> 
</UserControl.Resources> 

UnitControlBase:

/// <summary> 
/// Control that displays value in different units depending on selected unit type. 
/// </summary> 
/// <typeparam name="TSelectionTypeEnum">The enumeration type for all the available units.</typeparam> 
/// <typeparam name="TConverterType">The MultiValueConverter that converts the value between the different types of units.</typeparam> 
/// <typeparam name="TValueType">The underlying type of the stored value.</typeparam> 
public class UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType> : UserControl 
    where TSelectionTypeEnum : struct, IConvertible 
    where TConverterType : IMultiValueConverter, new() 
{ 
    #region Private Fields 

    // Metadata for the dependency properties. 
    private static FrameworkPropertyMetadata valuePropertyMetadata = new FrameworkPropertyMetadata(default(TValueType)); 
    private static FrameworkPropertyMetadata valueTypePropertyMetadata = new FrameworkPropertyMetadata(default(TSelectionTypeEnum)); 
    private static FrameworkPropertyMetadata displayValueTypePropertyMetadata = new FrameworkPropertyMetadata(default(TSelectionTypeEnum)); 
    private static FrameworkPropertyMetadata comboBoxWidthPropertyMetadata = new FrameworkPropertyMetadata(0.0); 
    private static FrameworkPropertyMetadata valueFormatPropertyMetadata = new FrameworkPropertyMetadata(string.Empty); 

    #endregion 

    #region Constructor 

    /// <summary> 
    /// Constructor 
    /// </summary> 
    public UnitControlBase() 
    { 
     ValueFormat = "#,##0.00"; 
     ComboBoxWidth = 75.0; 

     // Create main grid and add to control. 
     Grid mainGrid = new Grid(); 
     mainGrid.Name = "LayoutRoot"; 
     this.AddChild(mainGrid); 

     // Create grid columns. 
     ColumnDefinition col1 = new ColumnDefinition(); 
     col1.Width = GridLength.Auto; 
     ColumnDefinition col2 = new ColumnDefinition(); 
     mainGrid.ColumnDefinitions.Add(col1); 
     mainGrid.ColumnDefinitions.Add(col2); 

     // Create the text box that will display the value. 
     Label displayValueLabel = new Label(); 
     displayValueLabel.Name = "DisplayValueLabel"; 
     Grid.SetColumn(displayValueLabel, 0); 
     mainGrid.Children.Add(displayValueLabel); 

     // Bind to the multi-value converter that will convert between the types. 
     MultiBinding mb = new MultiBinding(); 
     mb.Converter = new TConverterType(); 
     mb.Bindings.Add(new Binding("Value") { Source = this }); 
     mb.Bindings.Add(new Binding("ValueType") { Source = this }); 
     mb.Bindings.Add(new Binding("DisplayValueType") { Source = this }); 
     mb.Bindings.Add(new Binding("ValueFormat") { Source = this }); 
     displayValueLabel.SetBinding(Label.ContentProperty, mb); 
     displayValueLabel.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Right;    

     // Create the combo box that will display selected unit. 
     ComboBox displayValueComboBox = new ComboBox(); 
     displayValueComboBox.Name = "DisplayValueComboBox"; 
     displayValueComboBox.SetBinding(ComboBox.WidthProperty, new Binding("ComboBoxWidth") { Source = this }); 
     Grid.SetColumn(displayValueComboBox, 1); 
     mainGrid.Children.Add(displayValueComboBox); 

     // Bind available units and selected units. 
     displayValueComboBox.ItemsSource = Enum.GetValues(typeof(TSelectionTypeEnum)); 
     displayValueComboBox.SetBinding(ComboBox.SelectedItemProperty, new Binding("DisplayValueType") { Source = this }); 
    } 

    #endregion 

    #region Dependency Properties 

    /// <summary> 
    /// Value Dependency Property 
    /// </summary> 
    public static readonly DependencyProperty ValueProperty = 
     DependencyProperty.Register("Value", typeof(TValueType), typeof(UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType>), valuePropertyMetadata); 

    /// <summary> 
    /// Value Type Dependency Property 
    /// </summary> 
    public static readonly DependencyProperty ValueTypeProperty = 
     DependencyProperty.Register("ValueType", typeof(TSelectionTypeEnum), typeof(UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType>), valueTypePropertyMetadata); 

    /// <summary> 
    /// Display Value Type Dependency Property 
    /// </summary> 
    public static readonly DependencyProperty DisplayValueTypeProperty = 
     DependencyProperty.Register("DisplayValueType", typeof(TSelectionTypeEnum), typeof(UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType>), displayValueTypePropertyMetadata); 

    /// <summary> 
    /// Combo Box Width Dependency Property 
    /// </summary> 
    public static readonly DependencyProperty ComboBoxWidthProperty = 
     DependencyProperty.Register("ComboBoxWidth", typeof(double), typeof(UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType>), comboBoxWidthPropertyMetadata); 

    /// <summary> 
    /// Value Format Dependency Property 
    /// </summary> 
    public static readonly DependencyProperty ValueFormatProperty = 
     DependencyProperty.Register("ValueFormat", typeof(string), typeof(UnitControlBase<TSelectionTypeEnum, TConverterType, TValueType>), valueFormatPropertyMetadata); 

    #endregion 

    #region Public Properties 

    /// <summary> 
    /// The underlying stored value. 
    /// </summary> 
    public TValueType Value 
    { 
     get 
     { 
      return (TValueType)GetValue(ValueProperty); 
     } 
     set 
     { 
      SetValue(ValueProperty, value); 
     } 
    } 

    /// <summary> 
    /// The unit type for the underlying stored value. 
    /// </summary> 
    public TSelectionTypeEnum ValueType 
    { 
     get 
     { 
      return (TSelectionTypeEnum)GetValue(ValueTypeProperty); 
     } 
     set 
     { 
      SetValue(ValueProperty, value); 
     } 
    } 

    /// <summary> 
    /// The unit type for the displayed value. 
    /// </summary> 
    public TSelectionTypeEnum DisplayValueType 
    { 
     get 
     { 
      return (TSelectionTypeEnum)GetValue(DisplayValueTypeProperty); 
     } 
     set 
     { 
      SetValue(DisplayValueTypeProperty, value); 
     } 
    } 

    /// <summary> 
    /// Width of combo box displaying available units. 
    /// </summary> 
    public double ComboBoxWidth 
    { 
     get 
     { 
      return (double)GetValue(ComboBoxWidthProperty); 
     } 
     set 
     { 
      SetValue(ComboBoxWidthProperty, value); 
     } 
    } 

    /// <summary> 
    /// The format of the displayed value. 
    /// </summary> 
    public string ValueFormat 
    { 
     get 
     { 
      return (string)GetValue(ValueFormatProperty); 
     } 
     set 
     { 
      SetValue(ValueFormatProperty, value); 
     } 
    } 

    #endregion 
} 

AngleUserControl.cs

/// <summary> 
/// Control allowing user to display a value in degrees, radians, or semicircles. 
/// </summary> 
public class AngleUserControl : UnitControlBase<AngleSelectionType, AngleMultiValueConverter, double> 
{ 
    #region Constructor 

    /// <summary> 
    /// Constructor. 
    /// </summary> 
    public AngleUserControl() 
    { 
     this.ComboBoxWidth = 175.0; 
    } 

    #endregion 
} 
+1

フルコントロールテンプレート – Steve

+0

@Steveを表示すると、両方のファイルが追加されています。 – bsh152s

+0

明らかにテンプレートはありません.C#コードを見ると、コントロールの構造は手動で構築されます。コンストラクタを見てください。 –

答えて

3

Aいわゆる "ローカル値"依存関係プロパティの例:

this.ComboBoxWidth = 175.0; 

<Setter Property="ComboBoxWidth" Value="400"/> 

ようしたがってスタイルセッターは影響を及ぼさない、スタイルセッターの値よりも高い値の優先順位を有します。

あなたは依存関係プロパティのメタデータをオーバーライドすることによって、新しいデフォルト値を割り当てる必要があります。

public class AngleUserControl : ... 
{ 
    static AngleUserControl() 
    { 
     ComboBoxWidthProperty.OverrideMetadata(
      typeof(AngleUserControl), 
      new PropertyMetadata(175d)); 
    } 
} 

は、参考のためにDependency Property Value Precedenceを参照してください。

+0

具体的なクラスが異なるデフォルト幅を持つ場合(基本クラスの幅が75、コンクリート175が設定されていることに注意してください)、OverrideMetadataを使用して具象クラスに異なるデフォルト値を設定します。 (https://msdn.microsoft.com/en-us/library/ms597491(v=vs.110).aspx) –

+0

@AdamSillsこれを指摘してくれてありがとう、私は答えを編集しました。 – Clemens

+0

ありがとう。それは魅力のように働いた。 – bsh152s

関連する問題