2017-02-07 2 views
1

У меня есть пользовательский элемент управления, который содержит поле со списком. Я добавил свойство зависимостей ComboBoxWidth, чтобы разработчик мог установить ширину, если захочет. Используя установщик стиля, я хотел бы установить ширину для всех этих комбинированных ящиков одинакового значения для другого пользовательского элемента управления для согласованности размеров. Но это не работает. Он работает, если я устанавливаю размер отдельно для каждого элемента управления. Когда размер указан в установщике стиля, он игнорируется. Если я изменил строку Property из «ComboBoxWidth» на «Width», изменится вся ширина всех элементов управления. Итак, похоже, что форматирование стиля верное. Я что-то упускаю? Это первый раз, когда я попытался применить стиль к своему собственному свойству зависимости.Редактор стиля WPF не работает

Примечание: AngleUserControl основан на общем пользовательском элементе управления (который не содержит никакого управления xaml, созданного в коде). Proberty от 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

так называемый "локальное значение" свойства зависимости, например

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

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