首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 ><EventTrigger RoutedEvent="Binding.TargetUpdated">不使用ContentTemplateSelector射击

<EventTrigger RoutedEvent="Binding.TargetUpdated">不使用ContentTemplateSelector射击
EN

Stack Overflow用户
提问于 2022-03-28 10:11:19
回答 1查看 104关注 0票数 0

当DataTemplate的子属性发生变化时,我试图在DataObject中为DataObject绘制边框的背景色。DataObject是一个名为Test的类,它有两个属性,数字和文本。我有一个叫数字的ObservableCollection of DataObjects。在“任务”中,我定期更新“数字”属性。

代码语言:javascript
复制
<Window
  x:Class="WpfAnimationTest.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:local="clr-namespace:WpfAnimationTest"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  Title="MainWindow"
  Width="800"
  Height="450"
  DataContext="{Binding Main, Source={StaticResource Locator}}"
  mc:Ignorable="d">
    <Grid>
        <Grid.Resources>
            <DataTemplate x:Key="NumberTemplate">
                <TextBlock Text="{Binding NotifyOnTargetUpdated=True}" />
            </DataTemplate>

            <local:ValueTemplateSelector x:Key="TemplateSelector">
                <local:ValueTemplateSelector.NumberTemplate>
                    <DataTemplate>
                        <ContentControl Content="{Binding NotifyOnTargetUpdated=True}" ContentTemplate="{StaticResource NumberTemplate}" />
                    </DataTemplate>
                </local:ValueTemplateSelector.NumberTemplate>
            </local:ValueTemplateSelector>

            <DataTemplate DataType="{x:Type local:Test}">
                <Border x:Name="UpdateBorder" Background="Aqua">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock
                          Width="50"
                          Margin="10"
                          Text="{Binding Text}" />
                        <ContentControl
                          Width="50"
                          Margin="10"
                          Content="{Binding Number}"
                          ContentTemplateSelector="{StaticResource TemplateSelector}" />

                        <!--
                            ContentTemplate="{StaticResource NumberTemplate}"
                        -->
                    </StackPanel>
                </Border>
                <DataTemplate.Triggers>
                    <EventTrigger RoutedEvent="Binding.TargetUpdated">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <Storyboard AutoReverse="True">
                                    <ColorAnimation
                                      FillBehavior="Stop"
                                      Storyboard.TargetName="UpdateBorder"
                                      Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                      To="#C5AFFFAA"
                                      Duration="00:00:0.5" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </Grid.Resources>
        <ListBox ItemsSource="{Binding Numbers}" />
    </Grid>
</Window>
代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace WpfAnimationTest
{
    public class Locator
    {
        public Locator()
        {
            Main = new Main();
        }

        public Main Main { get; set; }
    }

    public class Main
    {
        public ObservableCollection<Test> Numbers { get; set; } = new ObservableCollection<Test>();

        public Main()
        {
            var rnd = new Random(42);

            for (int i = 0; i < 10; i++)
            {
                Numbers.Add(new Test(){Number = i, Text = $"#: {i}"});
            }

            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {

                        Application.Current?.Dispatcher.Invoke(() =>
                        {
                            Numbers[rnd.Next(9)] = new Test
                            {
                                Number = rnd.Next(30),
                                Text = $"# {rnd.Next(30) + 30}"
                            };
                        });
                        Thread.Sleep(1000);

                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                        throw;
                    }
                }
            });

        }
    }

    public class Test
    {
        public int Number { get; set; }

        public string Text { get; set; }
    }

    
    public class ValueTemplateSelector : DataTemplateSelector
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <param name="container"></param>
        /// <returns></returns>
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            return !(item is Test value)
                ? null
                : NumberTemplate;
        }
        /// <summary>
        /// 
        /// </summary>
        public DataTemplate NumberTemplate { get; set; }
        
        /// <summary>
        /// 
        /// </summary>
        public DataTemplate DefaultTemplate { get; set; }
    }
}

当使用ContentTemplate作为ContentControl中的Number属性时,动画正在工作。但是当我使用ContentTemplateSelector时,动画就不再被触发了。

我在这里错过了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-28 10:57:33

您的数据绑定是错误的,会导致未处理或意外的数据类型。

当前,您的ContentControl.Content属性( DataTemplate中的Test类型)绑定到int类型的Test.Number属性。因此,传递给DataTemplateSelector的对象是int类型,而不是Test类型。DataTemplateSelector.SelectTemplate方法中的条件将返回false ( int is not Testtrue),并使DataTemplateSelector.SelectTemplate返回null -没有模板。XAML引擎将在ToString实例上调用int,因此能够正确地显示值(尽管缺少DataTemplate)。

解决方案

必须修复ContentControl.Content属性上的绑定,以绑定到Test实例,而不是绑定到Test.Number属性:

代码语言:javascript
复制
<DataTemplate DataType="{x:Type local:Test}">
    <Border x:Name="UpdateBorder"
            Background="Aqua">
      <StackPanel Orientation="Horizontal">
        <TextBlock Width="50"
                    Margin="10"
                    Text="{Binding Text}" />
        <ContentControl Width="50"
                        Margin="10"
                        Content="{Binding}"
                        ContentTemplateSelector="{StaticResource TemplateSelector}" />
      </StackPanel>
    </Border>

    ...
</DataTemplate>

既然DataTemplateSelector可以正常工作,您还必须调整NumberTemplate,以便它能够正确地显示Test.Number属性。由于我们修改了ContentControl.Content属性的绑定源,所以新的数据类型现在是Test (而不是int):

代码语言:javascript
复制
<DataTemplate x:Key="NumberTemplate"
              DataType="{x:Type Test}">
  <TextBlock Text="{Binding Number, NotifyOnTargetUpdated=True}" />
</DataTemplate>

备注

这里有很多多余的代码。您将通过正确定义DataTemplateSelector项的ItemTemplate来删除所有模板和Test,从而获得相同的结果。

下列大幅度简化的版本也应有效:

代码语言:javascript
复制
<Grid>
  <Grid.Resources>
    <DataTemplate DataType="{x:Type local:Test}">
      <Border x:Name="UpdateBorder"
              Background="Aqua">
        <StackPanel Orientation="Horizontal">
          <TextBlock Width="50"
                      Margin="10"
                      Text="{Binding Text}" />
          <TextBlock Width="50"
                      Margin="10"
                      Text="{Binding Number, NotifyOnTargetUpdated=True}" />
        </StackPanel>
      </Border>
      <DataTemplate.Triggers>
        <EventTrigger RoutedEvent="Binding.TargetUpdated">
          <EventTrigger.Actions>
            <BeginStoryboard>
              <Storyboard AutoReverse="True">
                <ColorAnimation FillBehavior="Stop"
                                Storyboard.TargetName="UpdateBorder"
                                Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
                                To="#C5AFFFAA"
                                Duration="00:00:0.5" />
              </Storyboard>
            </BeginStoryboard>
          </EventTrigger.Actions>
        </EventTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </Grid.Resources>

  <ListBox ItemsSource="{Binding Numbers}" />
</Grid>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71645753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档