XAML 处理UWP中ListView DataTemplate的数组项

v8wbuo2f  于 2023-04-18  发布在  其他
关注(0)|答案(1)|浏览(151)

我有下面的DataTemplate,我在UWP应用程序中使用它来定制ListView布局:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 7)"
    xmlns:utils="using:ClassevivaPCTO.Utils"
    x:Class="ClassevivaPCTO.Controls.DataTemplates.AgendaEventListViewDataTemplate"
    xmlns:muxc="using:Microsoft.UI.Xaml.Controls">

    <utils:AgendaEvent x:Key="AgendaEvent"/>

    <DataTemplate x:Key="AgendaEventListViewDataTemplate"
                  
                  x:DataType="utils:AgendaEvent">
        <RelativePanel>
    

                <TextBlock x:Name="eventTitle" TextWrapping="Wrap"
                                           MaxWidth="500"
                                           Text="{x:Bind subjectDesc}"
                                           Style="{ThemeResource BaseTextBlockStyle}"
                                           Margin="12,6,0,0" />

            <TextBlock RelativePanel.RightOf="eventTitle" x:Name="eventType" TextWrapping="Wrap"
                                           MaxWidth="500"
                                           Text="{x:Bind evtCode}"
                                           Style="{ThemeResource BaseTextBlockStyle}"
                                           Margin="12,6,0,0" />

        </RelativePanel>
    </DataTemplate>
</ResourceDictionary>

TextBlock项的Text值绑定到名为AgendaEvent的自定义数据类型类:

public class AgendaEvent
    {
        public int evtId { get; set; }
        public string evtCode { get; set; }
        public DateTime evtDatetimeBegin { get; set; }
        public DateTime evtDatetimeEnd { get; set; }
        public bool isFullDay { get; set; }
        public string notes { get; set; }
        public string authorName { get; set; }
        public string classDesc { get; set; }
        public object subjectId { get; set; }
        public object subjectDesc { get; set; }
        public object homeworkId { get; set; }
    }

这是我的ListView:

<ListView x:Name="ListViewAgendaEvents"
  SelectionMode="Single"
  HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
  ItemTemplate="{StaticResource AgendaEventListViewDataTemplate}"                   
 ScrollViewer.VerticalScrollMode="Disabled"
 ScrollViewer.VerticalScrollBarVisibility="Disabled">
</ListView>

从一个自定义数组工厂获得的AgendaEvent对象数组中,我将ItemsSource设置为ListView:

ListViewAgendaEvents.ItemsSource = customArray.AgendaEvents;

我意识到,为了满足我的需求,eventTitle TextBlock需要将authorNamesubjectDesc属性组合在一起,作为一个带有自定义装饰字符的字符串。authorName + " - wrote: " + subjectDesc
subjectDesc并不总是可用的,所以我需要使用各种条件检查来动态地调整eventTitle文本块。
我考虑过使用适配器类,就像Android的列表视图一样,但是使用UWP的数据绑定,如何完成我想做的事情非常令人困惑。
是否有一种简单直接的方法来合并自定义字符串中的属性,并在显示UWP中ListView中使用的DataTemplate的属性之前执行检查?

gdrx4gfi

gdrx4gfi1#

更新3

UWP不支持多个数据绑定,它只接受单个值。如果不想更改Xaml绑定,请尝试在DataModel中进行更改。在AgendaEvent类中创建新消息字符串并执行检查将是最简单的方法。

public class AgendaEvent
{
    public int evtId { get; set; }
    public string evtCode { get; set; }
    public DateTime evtDatetimeBegin { get; set; }
    public DateTime evtDatetimeEnd { get; set; }
    public bool isFullDay { get; set; }
    public string notes { get; set; }
    public string authorName { get; set; }
    public string classDesc { get; set; }
    public object subjectId { get; set; }
    public object subjectDesc { get; set; }
    public object homeworkId { get; set; }

    public string messageString
    {
        get
        {
            if (subjectDesc == null)
            {
                return authorName;
            }
            return authorName + " - wrote: " + subjectDesc;
        }
    }
}

Xaml:

<TextBlock x:Name="eventTitle" TextWrapping="Wrap"
                                       MaxWidth="500"
                                       Text="{x:Bind messageString}"
                                       Style="{ThemeResource BaseTextBlockStyle}"
                                       Margin="12,6,0,0" />

更新2:

我想出了另一种方法,它也应该能够实现你想要的。它需要不同的模板。你只需要选择不同的DataTemplate的值使用DataTemplateSelector Class
代码隐藏:

public class MyDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate Normal { get; set; }
    public DataTemplate Unusual { get; set; }

    protected override DataTemplate SelectTemplateCore(object item)
    {
        AgendaEvent agendaEvent = (AgendaEvent)item;
        // if you have other reuqirements, just need to add more check and different templates
        if (agendaEvent.subjectDesc != null)
        {
            return Normal;
        }
        else
        {
            return Unusual;
        }
    }
}

Xaml:

<Page.Resources>
     <!--tempalte for normal value-->
    <DataTemplate x:Key="NormalItemTemplate" x:DataType="local:AgendaEvent">
        <RelativePanel>
            <TextBlock x:Name="eventTitle" TextWrapping="Wrap"
                                       MaxWidth="500"
                                       Margin="12,6,0,0">
                            <Run Text="{x:Bind authorName}"/>
                            <Run Text=" - wrote: "/>
                            <Run Text="{x:Bind subjectDesc}"/>
            </TextBlock>
            <TextBlock RelativePanel.RightOf="eventTitle" x:Name="eventType" TextWrapping="Wrap"
                                       MaxWidth="500"
                                       Text="{x:Bind evtCode}"
                                       Margin="12,6,0,0" />

        </RelativePanel>
    </DataTemplate>
     <!--template for null value-->
    <DataTemplate x:Key="UnusualItemTemplate" x:DataType="local:AgendaEvent">
        <RelativePanel>
            <TextBlock x:Name="eventTitle" TextWrapping="Wrap"
                                       MaxWidth="500"
                                       Margin="12,6,0,0">
                            <Run Text="{x:Bind authorName}"/>
            </TextBlock>
            <TextBlock RelativePanel.RightOf="eventTitle" x:Name="eventType" TextWrapping="Wrap"
                                       MaxWidth="500"
                                       Text="{x:Bind evtCode}"
                                       Margin="12,6,0,0" />

        </RelativePanel>
    </DataTemplate>

    <local:MyDataTemplateSelector x:Key="MyDataTemplateSelector" 
                                  Normal="{StaticResource NormalItemTemplate}"
                                  Unusual="{StaticResource UnusualItemTemplate}"/>

</Page.Resources>

<Grid>
    <ListView x:Name="ListViewAgendaEvents"
              SelectionMode="Single"
              HorizontalAlignment="Stretch" 
              VerticalAlignment="Stretch"  
              ItemTemplateSelector="{StaticResource MyDataTemplateSelector}"
              ScrollViewer.VerticalScrollMode="Disabled"
              ScrollViewer.VerticalScrollBarVisibility="Disabled">
       
    </ListView>

</Grid>

更新:

您可以尝试创建一个自定义ValueConverter来完成这项工作。您可以在Converter事件中检查绑定值并自定义输出绑定字符串。
代码隐藏:

public class TextBlockValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value == null)
        {
            return "";
        }
        else 
        {
            return " - wrote: " + value.ToString();
        }

    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

Xaml:

<Page.Resources>
    <local:TextBlockValueConverter x:Key="TextBlockValueConverter"/>
</Page.Resources>

   <TextBlock x:Name="eventTitle" TextWrapping="Wrap"
                                       MaxWidth="500"
                                       Margin="12,6,0,0">
                          <Run Text="{x:Bind authorName}"/>
                          <Run Text="{x:Bind subjectDesc, Converter={StaticResource TextBlockValueConverter} }"/>
                    </TextBlock>

有没有一种简单直接的方法来合并UWP中ListView中使用的DataTemplate的自定义字符串中的属性?
既然你使用的是TextBlock,那么解决方案将非常简单。你只需要在TextBlock中使用Run。并将你想要的文本绑定到不同的Run
你只需要像这样修改代码:

<TextBlock x:Name="eventTitle" TextWrapping="Wrap"
                                       MaxWidth="500"
                                       Margin="12,6,0,0">
                          <Run Text="{x:Bind authorName}"/>
                          <Run Text=" - wrote: "/>
                          <Run Text="{x:Bind subjectDesc}"/>
                    </TextBlock>

结果如下所示:

相关问题