WPF / Windows 8应用程序DataTemplate Databind事件

时间:2013-12-14 00:44:22

标签: c# windows-8 windows-runtime winrt-xaml

我在ListView的DataTemplate中有一个RichTextBox控件。我的想法是,我想在绑定时动态地将运行/内联元素/图像等添加到Listview中的富文本框。问题是没有ondatabinding或类似的事件。我尝试了RichTextBox的Loaded事件,但看起来WPF重用了控件,所以当我滚动时内容被弄乱(错误的内容输入错误,因为加载事件在滚动期间触发)。我还应该提到通过手动向ListView.Items集合添加行,在代码隐藏中对ListView进行绑定。

相关标记

 <ListView Background="#F7F7F7" HorizontalAlignment="Stretch" Foreground="Black" x:Name="chatPane" Grid.Row="1" 
                  ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalContentAlignment="Stretch" SelectionMode="Multiple"
              ItemTemplateSelector="{StaticResource messageTypeDataTemplateSelector}" SelectionChanged="ChatPane_OnSelectionChanged">
        </ListView>

<common:MessageTypeDataTemplateSelector 
        TextMessageTemplate="{StaticResource TextMessage}" 
        EnterMessageTemplate="{StaticResource EnterMessage}" 
        ExitMessageTemplate="{StaticResource ExitMessage}"
        TimestampMessageTemplate="{StaticResource TimestampMessage}"
        ImageMessageTemplate="{StaticResource ImageMessage}"
        x:Key="messageTypeDataTemplateSelector" />

<DataTemplate x:Key="TextMessage">
        <Grid Grid.ColumnSpan="3" RowSpan="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition  Width="Auto"/>
                <ColumnDefinition Width=".5*"/>
                <ColumnDefinition Width="70*"/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding UserName}" Visibility="{Binding Source={StaticResource chatSettings}, Path=HideAvatars, Converter={StaticResource booleanToVisibility}}" FontWeight="Bold" TextAlignment="Right" Grid.Column="0" Width="150" />
            <Image VerticalAlignment="Top" Source="{Binding AvatarUrl}" Visibility="{Binding Source={StaticResource chatSettings}, Path=ShowAvatars, Converter={StaticResource booleanToVisibility}}" Grid.Column="0" Width="60" Margin="0,0,10,0" />
            <TextBlock Text=" : " Visibility="{Binding Source={StaticResource chatSettings}, Path=HideAvatars, Converter={StaticResource booleanToVisibility}}" Grid.Column="1"  />
            <RichTextBlock Loaded="FrameworkElement_OnLoaded" TextWrapping="Wrap" Grid.Column="2" />
        </Grid>
    </DataTemplate>

1 个答案:

答案 0 :(得分:4)

你是完全正确的。 WinRT中没有OnDataBinding事件。这个想法怎么样:

为RichTextBlock(http://msdn.microsoft.com/en-us/library/ms749011(v=vs.110).aspx)创建一个AttachedProperty,然后将您的项目绑定到该项目。当您注册Attached Property时,在FrameworkPropertyMetadata中,您可以指定一个PropertyChangedCallback,只要Attached Property的值发生更改,它就会触发。像这样:

目前,要确保它正常工作,请在当前的.xaml.cs文件中执行以下操作:

public static readonly DependencyProperty RichTextBlockItemProperty = DependencyProperty.RegisterAttached(
  "RichTextBlockItem",
  typeof(object),
  typeof(RichTextBlock),
  new PropertyMetadata(null, RichTextBlockItemChanged)
);

// Don't forget this!
public static object GetRichTextBlockItem(DependencyObject obj)
{
    return (object)obj.GetValue(RichTextBlockItemProperty);
}

// And this!
public static void SetRichTextBlockItem(DependencyObject obj, object value)
{
   obj.SetValue(RichTextBlockItemProperty, value);
}

public void RichTextBlockItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    // Here you can do whatever you wish. This method will fire when the item is bound.
    // d is the RichTextBlock object.
    // e.NewValue is the value that was just bound.
    // So, from here you can dynamically add your Runs/Images/etc
}

然后在.xaml文件中确保添加本地命名空间,以便执行此操作:

<Page .... xmlns:local="using:CurrentXamlPageNamespace".../>

<DataTemplate x:Key="TextMessage">
    <Grid Grid.ColumnSpan="3" RowSpan="1">
        <!-- I got rid of the other xaml just to hightlight my answer. But you still need it. -->
        <RichTextBlock local:RichTextBlock.RichTextBlockItem="{Binding}" TextWrapping="Wrap" Grid.Column="2" />
    </Grid>
</DataTemplate>