没有为ContentControl派生类型调用WPF DataTemplateSelector.SelectTemplate

时间:2009-07-17 07:19:58

标签: wpf datatemplate datatemplateselector

我正在尝试构建一个ContentControl派生的控件(我们称之为MyContentControl),它将ControlTemplate的{​​{1}}设置为派生DataTemplateSelector输入(我们称之为MyTemplateSelector)。

当我尝试这个时:

ContentControl contentControl = new ContentControl();
contentControl.ContentTemplateSelector = new MyTemplateSelector();
contentControl.Content = "Some ContentControl Content";

MyContentControl myContentControl = new MyContentControl();    
myContentControl.ContentTemplateSelector = new MyTemplateSelector();
myContentControl.Content = "Some MyControl Content";

我希望,当我在这些控件上设置内容时,会MyTemplateSelectorDataTemplateSelector.SelectTemplate()调用contentControl覆盖myContentControl方法。

实际上,只为contentControl调用它。我需要做什么(以及为什么!)使其适用于myContentControl

(不确定它是否相关,但目前MyContentControl除了覆盖DependencyProperties的元数据信息外,对DefaultStyleKeyProperty不执行任何操作。

编辑(将内容从其他帖子转移到原始问题):

这是一个更详细的例子:

  1. 创建MyContentControl:

    public class MyContentControl : ContentControl
    {
      static MyContentControl()
      {
        DefaultStyleKeyProperty.OverrideMetadata(typeof (MyContentControl),
                                             new FrameworkPropertyMetadata(typeof (MyContentControl)));
      }
      public MyContentControl() {}
    }
    
  2. 创建MyTemplateSelector

    public class MyTemplateSelector : DataTemplateSelector
    {
      public override DataTemplate SelectTemplate(object item, DependencyObject container)
      {
        return null;  // <== Place the breakpoint here
      }
    }
    
  3. ContentControlMyContent控件添加到主窗口(例如):

    <StackPanel>
        <local:MyContentControl x:Name="myContentControl" />
        <ContentControl x:Name="contentControl" />
    </StackPanel>
    
  4. InitializeComponent(或Loaded处理程序)之后的某处添加此代码:

    myContentControl.ContentTemplateSelector = new MyTemplateSelector();
    myContentControl.Content = "123";
    
    contentControl.ContentTemplateSelector = new MyTemplateSelector();
    contentControl.Content = "ABC";
    
  5. 对于content="ABC"contentControl元素,步骤(2)中提到的断点只被命中一次。

3 个答案:

答案 0 :(得分:2)

之前我遇到了同样的问题,我用这个(Notify DataTemplateSelector about the change)提示解决了这个问题。

我的问题是,我想要一个ContentPresenter,当ComboBox选择发生变化时,它会更改嵌入式UserControl。

Combobox + ContentPresenter XAML

        <ComboBox Name="comboBoxControl" Grid.Row="1" Grid.Column="1" SelectionChanged="comboBox_SelectionChanged">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <cmd:EventToCommand Command="{Binding Path=ChangeControlCommand, Mode=OneWay}" CommandParameter="{Binding Path=SelectedItem.Content, ElementName=comboBoxControlType}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <ComboBoxItem>UserControl-1-</ComboBoxItem>
        <ComboBoxItem>UserControl-2-</ComboBoxItem>
    </ComboBox>
<ContentPresenter Name="contentPresenter" ContentTemplateSelector="{Binding Source={StaticResource controlCueTemplateSelector}}" 
                      Content="{Binding}" />

正如您所看到的,使用MVVM方式绑定命令是我的方法。虽然您可能不想编写代码隐藏,但请使用适当的事件编写代码隐藏,如下所示。

    private void comboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var content = contentPresenter.Content;
        contentPresenter.ClearValue(ContentPresenter.ContentProperty);
        contentPresenter.SetValue(ContentPresenter.ContentProperty, content);
    }

Bottomline是,你需要重置绑定的目标对象(在我的例子中,是Content属性)。

答案 1 :(得分:2)

我遇到了同样的问题,DataTemplateSelector已经应用于ContentControl而不是我的派生控件的原因隐藏在我的派生控件的ControlTemplate中。我只是忘了为ContentTemplateSelector添加模板绑定:

<ControlTemplate TargetType="{x:Type local:UniControl}">
<Border Background="{TemplateBinding Background}"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="{TemplateBinding BorderThickness}">
    <ContentPresenter Content="{TemplateBinding Content}"
                        ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"/>
</Border>

希望这有帮助。

答案 2 :(得分:0)

您可能需要发布更多代码,因为我刚创建了一个简单的示例,它运行正常。我的DataTemplate只包含TextBox,我的DataTemplateSelector始终返回DataTemplate,而ContentControl和来自ContentControl的类都使用我的DataTemplateSelector TextBox。在这两种情况下都显示了{{1}}。