WPF Control шаблон на пользовательский контроль - PullRequest
2 голосов
/ 08 июля 2011

Я создал свой собственный элемент управления в WPF. Первоначально я создал его как пользовательский контроль, но нашел, что предпочтительный способ сделать это - создать класс, который наследует от элемента управления, а затем поместить свой соответствующий xaml в шаблон элемента управления внутри Generic.xaml. Это работало нормально, когда оно было в моем exe, но когда я переместил его в dll, граница исчезла из моего контроля. Мой элемент управления основан на текстовом поле и представляет собой копию и вставку шаблона элемента управления текстового поля с добавлением кнопки, по которой пользователь может щелкнуть. Я идентифицировал соответствующую часть шаблона элемента управления, которая не работает, это бит BorderBrush = "{TemplateBinding Border.BorderBrush}" ниже, а также следующая строка.

<Style TargetType="{x:Type local:ButtonBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ButtonBox}">
                <mwt:ListBoxChrome 
                        Background="{TemplateBinding Panel.Background}"
                        BorderBrush="{TemplateBinding Border.BorderBrush}"
                        BorderThickness="{TemplateBinding Border.BorderThickness}"
                        RenderMouseOver="{TemplateBinding UIElement.IsMouseOver}"
                        RenderFocused="{TemplateBinding UIElement.IsKeyboardFocusWithin}"
                        Name="Bd"
                        SnapsToDevicePixels="True">

Я понимаю привязку шаблона, но не понимаю, почему мы привязываем Border.BorderBrush. Где граница, к которой мы привязаны? Визуальное дерево не показывает границы, которая является частью моего контроля. Если я заменю эти 2 строки жестко закодированными значениями, то получу границу. Я подозреваю, что может быть что-то отсутствует в DLL, что exe-файл, такой как стиль или что-то, что относится к границе ??

Заранее спасибо за любые ответы и всем, кто нашел время, чтобы прочитать. Ура, Michael

1 Ответ

2 голосов
/ 04 августа 2011

Я наконец разобрался с этим.Чтобы ответить на мой первый вопрос «Почему мы используем Border.BorderBrush в этом коде, если в шаблоне элемента управления не определена граница»:

BorderBrush="{TemplateBinding Border.BorderBrush}"

Граница в Border.BorderBrush существует, поскольку свойство зависимости являетсяопределены в классе границы.Хотя Control имеет свойство зависимости BorderBrush, это свойство фактически определено в Border.то есть, как это определено в Border

BorderBrushProperty = DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(Border), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(Border.OnClearPenCache)));

, и как это используется в Control

BorderBrushProperty = Border.BorderBrushProperty.AddOwner(typeof(Control), new FrameworkPropertyMetadata(Border.BorderBrushProperty.DefaultMetadata.DefaultValue, FrameworkPropertyMetadataOptions.None));

Ключевым моментом здесь является то, что Control не определяет свою собственную зависимостьсвойство BorderBrush, вместо этого он использует AddOwner, чтобы связать себя с существующим свойством зависимости.Вот почему он определен как Border.BorderBrush в шаблоне элемента управления, даже если текстовое поле не имеет границы в шаблоне элемента управления.

Ответ на мой второй вопрос «где установлено это значение» заключается в том, чтоэто установлено в стиле по умолчанию текстового поля.Я могу взглянуть на стиль по умолчанию для текстового поля, выполнив следующее:

            var style = (Style)Application.Current.TryFindResource(typeof(TextBox));
            if (style == null) return;
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            StringBuilder sb = new StringBuilder();
            XmlWriter writer = XmlWriter.Create(sb, settings);
            XamlWriter.Save(style, writer);
            MessageBox.Show(sb.ToString());

Как только мы запустим этот код, мы увидим, что в стиле оба свойства жестко запрограммированы.Мне это кажется странным, но, очевидно, так оно и было.

  <Setter Property="Border.BorderBrush">
    <Setter.Value>
      <LinearGradientBrush StartPoint="0,0" EndPoint="0,20" MappingMode="Absolute">
        <LinearGradientBrush.GradientStops>
          <GradientStop Color="#FFABADB3" Offset="0.05" />
          <GradientStop Color="#FFE2E3EA" Offset="0.07" />
          <GradientStop Color="#FFE3E9EF" Offset="1" />
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </Setter.Value>
  </Setter>
  <Setter Property="Border.BorderThickness">
    <Setter.Value>
      <Thickness>1,1,1,1</Thickness>
    </Setter.Value>
  </Setter>

После того, как я скопировал, вставил это в стиль для моего контроля, все заработало, как и ожидалось.

Просто, эй?: -)))

...