如何参考PART_XXX

时间:2013-01-21 22:46:30

标签: wpf custom-controls

将自定义控件模拟为一个窗口并且所有行为都正确,我现在正试图将其转换为适当的自定义控件(称为“When”,它是一个日期时间窗口小部件)。

我准备了一个When.XAML文件,其子元素名为PART_xxx

<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:glob="clr-namespace:System.Globalization;assembly=mscorlib"
  xmlns:local="clr-namespace:Widgets">
  <local:DatePartPositionValueConverter x:Key="DatePartPositionValueConverter" />
  <local:DatePartVisibilityValueConverter x:Key="DatePartVisibilityValueConverter" />
  <Style TargetType="{x:Type local:When}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:When}">
          <Border Background="{TemplateBinding Background}"
                  BorderBrush="{TemplateBinding BorderBrush}"
                  BorderThickness="{TemplateBinding BorderThickness}">
            <Border BorderThickness="1" BorderBrush="{DynamicResource 
                {x:Static SystemColors.ControlDarkBrushKey}}">
              <Grid HorizontalAlignment="Left" Margin="4,0,0,0">
                <Grid.ColumnDefinitions>
                  <ColumnDefinition />
                  ...
                  <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <TextBlock x:Name="PART_year" Grid.Column="{Binding 
                    Converter={StaticResource DatePartPositionValueConverter}, 
                    ConverterParameter=y}">
                  <TextBlock.Text>
                  ...

自定义控件项目Generic.XAML文件引用When.XAML

<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/Widgets;component/Themes/When.xaml" />
  </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

但是,我的代码似乎无法解析PART_名称。

我希望能够将_focussedElement与(例如)PART_year进行比较,以提供验证检查的上下文。必须可以从自定义控件的代码直接引用PART_xxx,否则将无法使用代码将事件处理程序绑定到模板的元素。

我没有理解什么?


为了解释并扩展下面的优秀答案,PART_year 不在范围内,因为IDE的代码生成魔法没有机会将其纳入范围。因此,您自己将其纳入范围,如下所示:

MenuItem PART_MenuItemToday, PART_MenuItemNow, 
  PART_MenuItemMonthEnd, PART_MenuItemMonthStart;
public override void OnApplyTemplate()
{
  base.OnApplyTemplate();
  PART_MenuItemMonthEnd = GetTemplateChild("PART_ContextMenuMonthEnd") as MenuItem;
  PART_MenuItemMonthEnd.Click += PART_ContextMenuMonthEnd_Click;
  ...
}

当您需要将同一组处理程序挂钩到多个小部件时,您可以执行此操作

private void BindGenericHandlers(TextBlock textBlock)
{
  textBlock.GotFocus += PART_GotFocus;
  textBlock.LostFocus += PART_LostFocus;
  textBlock.MouseDown += PART_MouseDown;
  textBlock.MouseEnter += PART_MouseEnter;
  textBlock.MouseLeave += PART_MouseLeave;
}

TextBlock _focussedElement, PART_year, PART_month, PART_day, PART_hour, PART_minute, PART_second, PART_designator;

public override void OnApplyTemplate()
{
  base.OnApplyTemplate();
  BindGenericHandlers(PART_day = GetTemplateChild("PART_day") as TextBlock);
  BindGenericHandlers(PART_designator = GetTemplateChild("PART_designator") as TextBlock);
  BindGenericHandlers(PART_hour = GetTemplateChild("PART_hour") as TextBlock);
  BindGenericHandlers(PART_minute = GetTemplateChild("PART_minute") as TextBlock);
  BindGenericHandlers(PART_month = GetTemplateChild("PART_month") as TextBlock);
  BindGenericHandlers(PART_second = GetTemplateChild("PART_second") as TextBlock);
  BindGenericHandlers(PART_year = GetTemplateChild("PART_year") as TextBlock);
  ...
}

1 个答案:

答案 0 :(得分:2)

您可以使用GetTemplateChild覆盖中的OnApplyTemplate方法在代码中检索对PART的引用。因此,在您的控件代码中,您将拥有以下内容:

private const string PART_TEXTINPUT = "PART_TEXT";
private TextBox _textInput;

public override void OnApplyTemplate()
{
   base.OnApplyTemplate();
   _textInput = GetTemplateChild(PART_TEXTINPUT) as TextBox;
}

由于您正在使用PART,因此您似乎在进行无形控制,因此,您无法直接引用XAML中的元素(因为自定义ControlTemplate可能会将其替换为意外的内容)。因此,您使用GetTemplateChild方法检索对PART的引用。

注意:如果有人用不同的实现替换了您的预期控件,请务必使用该部件的最低类型(在您的代码中)。