Wpf 如何参考第XXX部分

Wpf 如何参考第XXX部分,wpf,custom-controls,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"

将自定义控件模拟为一个窗口,并使所有行为正确,现在我正尝试将其转换为一个适当的自定义控件(称为“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>
                  ...
当您需要将同一组处理程序挂接到多个小部件时,您可以这样做

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);
  ...
}

您可以使用应用程序模板覆盖中的
GetTemplateChild
方法检索对代码中部件的引用。因此,在控件的代码中,您将具有以下内容:

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

public override void OnApplyTemplate()
{
   base.OnApplyTemplate();
   _textInput = GetTemplateChild(PART_TEXTINPUT) as TextBox;
}
因为您使用的是部件,所以您似乎在创建一个无外观控件,因此,您不能从XAML直接引用元素(因为自定义
ControlTemplate
可能会用意外的内容替换它)。因此,您可以使用
GetTemplateChild
方法检索对零件的引用


注意:确保为部件使用尽可能低的类型(在代码中),以防有人用不同的实现替换您的预期控件。

+1-是的,我正在创建一个无外观控件。我知道您不能直接引用,IDE通常不会生成代码,这与绑定事件处理程序的需要相结合,让我非常困惑。你的答案正是我想要的。除了作为UserControl派生控件之外,是否有可能创建一个“lookful”自定义控件?Peter,请详细说明你试图实现的目标。您可以直接从现有控件派生,例如
公共类CustomTextBox:TextBox
。这就是你的意思吗?另一个注意事项-你可能想看看
TemplatePart
属性,作为一种通知那些使用你的控件的人他们应该知道哪些部分的方式。多亏了你的帮助,我已经完成了最初的目标,那就是构建一个从控件派生并使用组合的无外观日期时间小部件。现在我只是把我无知的界限推了回去。你没有误解什么,我扩大了我的好奇心。
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);
  ...
}
private const string PART_TEXTINPUT = "PART_TEXT";
private TextBox _textInput;

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