【问题标题】:XAML ItemsControl items not showingXAML ItemsControl 项目未显示
【发布时间】:2014-03-17 20:01:43
【问题描述】:

我正在尝试将 XAML WP8 代码转换为 WPF。目的是以聊天气泡样式显示对话,适用于 WP8。

它由一个存储消息信息的 Message 对象、一个将它们存储为 ObservableCollection 的 MessageCollection 对象和一个继承 ContentControl 的 ContentPresenter 组成。在那里定义了两个 DataTemplate,应该由 xaml 代码选择。

我已经搜索了几天并尝试了所有方法,但是每当我启动项目时,它只会显示“ChatBubble.Message”(这是一个消息对象),因此没有应用任何文本和模板。布局本身在没有 itemscontrol 绑定的情况下进行测试。

我尝试在 ContentPresenter 中使用 Debug.Show 进行调试,结果证明它确实可以被 ConversationView 访问。它还表明它确实包含我添加的测试数据,并区分了两个模板(MeTemplate 和 YouTemplate 用于将气泡放置在右侧或左侧)。

ConversationView,在 XAML 中显示气泡:

<Grid x:Name="LayoutRoot" Background="Black">
    <ItemsControl ItemsSource="{Binding}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <local:MessageContentPresenter Content="{Binding}">
                    <local:MessageContentPresenter.MeTemplate>
                        <DataTemplate>
                            <Grid Margin="30, 10, 5, 0"
                  local:GridUtils.RowDefinitions=",,"
                  Width="420">
                                <Rectangle Fill="White"
                         Grid.RowSpan="2"/>
                                <TextBlock Text="{Binding Path=Text}"
                         Style="{StaticResource TextBlockStyle}"/>
                                <TextBlock Text="{Binding Path=Timestamp, Converter={StaticResource StringFormatConverter}, ConverterParameter='ddd, HH:mm'}"
                         Style="{StaticResource TimestampStyle}"
                         Grid.Row="1"/>
                                <Path Data="m 0,0 l 16,0 l 0,16 l -16,-16"
                    Fill="White"
                    Margin="0,0,5,0"
                    HorizontalAlignment="Right"
                    Grid.Row="2"/>
                            </Grid>
                        </DataTemplate>
                    </local:MessageContentPresenter.MeTemplate>
                    <local:MessageContentPresenter.YouTemplate>
                        <DataTemplate>
                            <Grid Margin="5, 10, 30, 0"
                  local:GridUtils.RowDefinitions=",,"
                  Width="420">

                                <Path Data="m 0,0 l 0,16 l 16,0 l -16,-16"
                    Fill="White"
                    Margin="5,0,0,0"
                    HorizontalAlignment="Left"/>
                                <Rectangle Fill="White"
                         Grid.Row="1" Grid.RowSpan="2"/>
                                <TextBlock Text="{Binding Path=Text}"
                         Style="{StaticResource TextBlockStyle}"
                         Grid.Row="1"/>
                                <TextBlock Text="{Binding Path=Timestamp, Converter={StaticResource StringFormatConverter}, ConverterParameter='ddd, HH:mm'}"
                         Style="{StaticResource TimestampStyle}"
                         Grid.Row="2"/>
                            </Grid>
                        </DataTemplate>
                    </local:MessageContentPresenter.YouTemplate>
                </local:MessageContentPresenter>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>          
</Grid>

这是 ContentPresenter:

public class MessageContentPresenter : ContentControl
{
    public DataTemplate MeTemplate { get; set; }

    public DataTemplate YouTemplate { get; set; }

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        Message message = newContent as Message;

        if (message.Side == MessageSide.Me)
        {
            ContentTemplate = MeTemplate;
        }
        else
        {
            ContentTemplate = YouTemplate;
        }
    }

知道我错过了什么吗?

【问题讨论】:

  • 只是想澄清一下。你在哪里看到ChatBubble.Message?它是在 datatemplate 内的文本块中,还是直接在 itemscontrol 内(意思是 itemtemplate/datatemplate 没有被使用)?
  • 当我删除&lt;ItemsControl ItemsSource="{Binding}"&gt; 标签之间的所有内容时,它仍然显示ChatBubble.Message,所以我从那里假设。
  • 作为我之前声明的补充:它确实循环通过 itemtemplate/datatemplate,因为 ContentPresenter 中的 Debug.Print 表明它已被访问。
  • 如果您在 datatemplate 中硬编码文本块的文本而不是使用绑定,是显示硬编码文本还是仍然ChatBubble.Message
  • 还是ChatBubble.Message

标签: c# wpf xaml


【解决方案1】:

在 WPF 中,您通常会使用 DataTemplateSelector 为每个项目选择正确的 DataTemplate:

public class MessageTemplateSelector : DataTemplateSelector
{
    public DataTemplate MeTemplate { get; set; }
    public DataTemplate YouTemplate { get; set; }

    public override DataTemplate SelectTemplate(
        object item, DependencyObject container)
    {
        var message = item as Message;
        return message.Side == MessageSide.Me ? MeTemplate : YouTemplate;
    }
}

您可以将它分配给 ItemsControl 的 ItemTemplateSelector 属性,如下所示:

<Window.Resources>
    <DataTemplate x:Key="MeTemplate">
        ...
    </DataTemplate>
    <DataTemplate x:Key="YouTemplate">
        ...
    </DataTemplate>
</Window.Resources>
...
<ItemsControl ItemsSource="{Binding}">
    <ItemsControl.ItemTemplateSelector>
        <local:MessageTemplateSelector
            MeTemplate="{StaticResource MeTemplate}"
            YouTemplate="{StaticResource YouTemplate}"/>
    </ItemsControl.ItemTemplateSelector>
</ItemsControl>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多