在WPF中的ItemsControl的DataTemplate中运行时访问TextBlock的文本

时间:2012-09-28 11:53:28

标签: wpf time datatemplate textblock

我在WPF应用程序中显示消息
当一条新消息被添加到消息中时,我需要突出显示它。所以我想动态地将文本添加到TextBlock

我有像这样的xaml

 <ItemsControl Name="DialogItemsControl" ItemsSource="{Binding Messages, Mode=OneWay}" Background="Transparent" 
                          BorderBrush="Transparent" TargetUpdated="DialogItemsControl_TargetUpdated">
                <ItemsControl.ItemTemplate><!-- For ever message -->
                    <DataTemplate>
                        <Grid Margin="0,0,0,20">
                            <ItemsControl Name="SubDialogItemsControl"
                                  Foreground="{DynamicResource ButtonTextBrush}" 
                                  ItemsSource="{Binding Lines,NotifyOnTargetUpdated=True}"
                                  Margin="0,0,0,12"
                                  Grid.Column="0">
                                <ItemsControl.ItemTemplate><!-- For every line -->
                                    <DataTemplate>
                                        <TextBlock Name="DialogMessageText" 
                                                   Text="{Binding NotifyOnTargetUpdated=True}" 
                                            VerticalAlignment="Top" 
                                            Margin="0,2,0,2" 
                                            TextTrimming="WordEllipsis"/>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>                                    
                            </ItemsControl>
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>

并且codebehind类中的代码是这样的:

private void DialogItemsControl_TargetUpdated(object sender, System.Windows.Data.DataTransferEventArgs e)
        {  
          ItemsControl itemControl = sender as ItemsControl;

            ContentPresenter dp =   itemControl.ItemContainerGenerator.ContainerFromItem(itemControl.Items.CurrentItem) as ContentPresenter;

            // Finding textBlock from the DataTemplate that is set on that ContentPresenter
            DataTemplate myDataTemplate = dp.ContentTemplate;
            ItemsControl itc = (ItemsControl)myDataTemplate.FindName("SubDialogItemsControl", dp);
            if (itc != null && itc.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
            {
                ContentPresenter cp = itc.ItemContainerGenerator.ContainerFromIndex(0) as ContentPresenter;
                DataTemplate dt = cp.ContentTemplate;
                TextBlock tb = dt.LoadContent() as TextBlock;               

                tb.TargetUpdated += new EventHandler<System.Windows.Data.DataTransferEventArgs>(myTextBlock_TargetUpdated);
            }            
        }

 void myTextBlock_TargetUpdated(object sender, System.Windows.Data.DataTransferEventArgs e)

       {

            TextBlock tb = sender as TextBlock;
           //When i access the text property of tb, its showing null, how to get the text
        }

当我在textblock的目标更新事件中访问textblock的text属性时,它显示为null,如何读取文本。

提前致谢

1 个答案:

答案 0 :(得分:0)

您从错误的角度处理问题(并且可能在此过程中添加了内存泄漏,因为我没有看到您取消订阅事件)。

您需要创建一个自定义TextBlock,覆盖Text属性的元数据,以便在文本字符串更改时通过PropertyChangedCallback更改背景几秒钟。

然后在ItemsControl的DataTemplate中使用该自定义TextBlock。

编辑 - 我认为其他人可能需要此功能,所以这是一个有效的例子:

public class CustomTextBlock : TextBlock
    {
        static CustomTextBlock()
        {
            TextProperty.OverrideMetadata(typeof(CustomTextBlock), new FrameworkPropertyMetadata(null, 
                new PropertyChangedCallback(
                    (dpo, dpce) => 
                    {
                        //Flash the background to yellow for 2 seconds
                        var myTxtblk = dpo as CustomTextBlock;
                        if (myTxtblk != null)
                        {
                            myTxtblk.Background = Brushes.Yellow;
                            Task.Factory.StartNew(
                                () => 
                                {
                                    Thread.Sleep(2000);
                                    Application.Current.Dispatcher.Invoke(
                                        new Action(() => 
                                        {
                                            myTxtblk.Background = Brushes.Transparent;
                                        }));
                                });
                        }
                    })));
        }
    }

然后你需要在XAML视图中声明正确的xmlns命名空间,并像普通的TextBlock一样使用它:

<local:CustomTextBlock Text="{Binding MyDynamicText}"/>

修改MyDynamicText时会闪烁黄色(只要它引发了PropertyChanged)。