未针对 ContentControl 派生类型调用 WPF DataTemplateSelector.SelectTemplate

发布于 2024-07-26 19:18:05 字数 2509 浏览 13 评论 0原文

我正在尝试构建一个 ContentControl 派生控件(我们称之为 MyContentControl),该控件的 ControlTemplate的实例设置。 code>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() 方法的重写会为两个 调用contentControlmyContentControl

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

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

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

这是一个更详细的示例:

  1. 创建 MyContentControl:

    公共类 MyContentControl : ContentControl 
      { 
        静态 MyContentControl() 
        { 
          DefaultStyleKeyProperty.OverrideMetadata(typeof (MyContentControl), 
                                               新的 FrameworkPropertyMetadata(typeof (MyContentControl))); 
        } 
        公共 MyContentControl() {} 
      } 
      
  2. 创建 MyTemplateSelector

    公共类 MyTemplateSelector :DataTemplateSelector 
      { 
        公共覆盖 DataTemplate SelectTemplate(对象项,DependencyObject 容器) 
        { 
          返回空值;   // <== 在此处放置断点 
        } 
      } 
      
  3. ContentControlMyContent控件添加到主窗口(例如):< /p>

    ; 
           
           
       
      
  4. 将此代码添加到 InitializeComponent 之后的某个位置 code> (或在 Loaded 处理程序中):

    myContentControl.ContentTemplateSelector = new MyTemplateSelector(); 
      myContentControl.Content = "123"; 
    
      contentControl.ContentTemplateSelector = new MyTemplateSelector(); 
      contentControl.Content = "ABC"; 
      

步骤 (2) 中提到的断点仅被命中一次,对于 < code>content="ABC" 和 contentControl 元素。

I'm trying to build a ContentControl-derived control (let's call it MyContentControl) that will have its ControlTemplate set by an instance of a DataTemplateSelector-derived type (let's call it MyTemplateSelector).

When I try to this:

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";

I expect that, when I set content on those controls, MyTemplateSelector's override of DataTemplateSelector.SelectTemplate() method gets called for both contentControl and myContentControl.

In reality, it gets called only for contentControl. What do I need to do (and why!) to make it work for myContentControl too?

(Not sure if it's relevant, but for the moment MyContentControl does not do anything with DependencyProperties other than overriding metadata information for DefaultStyleKeyProperty.

EDIT (moved content from other post to original question):

Here is a bit more elaborated example:

  1. Create MyContentControl:

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

    public class MyTemplateSelector : DataTemplateSelector
    {
      public override DataTemplate SelectTemplate(object item, DependencyObject container)
      {
        return null;  // <== Place the breakpoint here
      }
    }
    
  3. Add ContentControl and MyContent control to your main window (for example):

    <StackPanel>
        <local:MyContentControl x:Name="myContentControl" />
        <ContentControl x:Name="contentControl" />
    </StackPanel>
    
  4. Add this code somewhere after InitializeComponent (or in Loaded handler):

    myContentControl.ContentTemplateSelector = new MyTemplateSelector();
    myContentControl.Content = "123";
    
    contentControl.ContentTemplateSelector = new MyTemplateSelector();
    contentControl.Content = "ABC";
    

The breakpoint mentioned in step (2) gets hit only once, for content="ABC" and contentControl element.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

逆流 2024-08-02 19:18:05

我之前遇到过同样的问题,我用这个解决了它(通知 DataTemplateSelector 有关更改) 提示。

我的问题是,我想要一个 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);
    }

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

I got the same problem before, and I solve it with this (Notify DataTemplateSelector about the change) hint.

My problem was, I want a ContentPresenter which changes embedded UserControl when the ComboBox selection changed.

The Combobox+ContentPresenter XAML is

        <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}" />

As you can see, the command binding with MVVM manner was my approach. Although you might not want to write a code-behind, kindly write a code-behind with appropriate event as below.

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

Bottomline is, you need to reset the binded target object (in my case, the Content property).

暗喜 2024-08-02 19:18:05

我刚刚遇到了同样的问题,并且 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>

希望这可以帮助。

I just had the same problem and the reason that the DataTemplateSelector has been applied for a ContentControl but not for my derived Control was hidden in the ControlTemplate for my derived Control. I simply forgot to add the template binding for the 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>

Hope this helps.

咋地 2024-08-02 19:18:05

您可能需要发布更多代码,因为我刚刚创建了一个简单的示例并且它运行良好。 我的 DataTemplate 仅包含一个 TextBox,我的 DataTemplateSelector 始终返回该 DataTemplate,并且都有一个 ContentControl< /code> 和从 ContentControl 派生的类使用我的 DataTemplateSelector。 在这两种情况下,都会显示一个 TextBox

You might need to post more of your code, because I just created a simple example and it worked fine. My DataTemplate only contains a TextBox, my DataTemplateSelector always returns that DataTemplate, and both a ContentControl and a class derived from ContentControl use my DataTemplateSelector. In both cases a TextBox was displayed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文