WPF在XAML中的对象列表中显示字符串数组

本文关键字:显示 字符串 数组 列表 XAML WPF 对象 | 更新日期: 2023-09-27 18:28:23

在当前项目中,我有一个对象列表。其中2个属性的类型为string[]。

目前,我可以用它们的主要标识符显示项目的数量。但除此之外,我还想显示指定字符串[]中的所有不同字符串。

类看起来是这样的:

public class TimeStamp
{
    public int ID { get; set; }
    public string[] DaysOfWeek { get; set; }
    public string[] HoursOfDay { get; set; }
}

在我的页面中,我有以下(如上所述工作)

    <ListView x:Name="listboxFolder1"  Grid.Row="2" Margin="5" Grid.ColumnSpan="4" 
        ItemsSource="{Binding}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Border BorderBrush="Blue" Margin="3" Padding="3" BorderThickness="2" CornerRadius="0 25 0 25" Background="Beige" HorizontalAlignment="Stretch">
                    <StackPanel Orientation="Horizontal">
                        <Image Margin="10" Width="50" Height="50" Stretch="Fill" Source="/Images/watch.png">
                            <Image.BitmapEffect>
                                <DropShadowBitmapEffect />
                            </Image.BitmapEffect>
                        </Image>
                        <StackPanel Orientation="Vertical" VerticalAlignment="Center">
                            <TextBlock Text="{Binding ID}"/>
                            <TextBlock Text="{Binding DaysOfWeek}"/>
                        </StackPanel>
                    </StackPanel>
                </Border>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

并且为了完成,绑定的设置:

    static List<iBackupModel.Models.TimeStamp> mySchedules { get; set; }
    public Scheduler()
    {
        InitializeComponent();
        listboxFolder1.ItemsSource = Home.mySettings.TimeStamps;
    }

但是DaysOfWeek显示为:String[]-matrix。

我希望它像"星期一|星期五|星期天"。

如果有可能将其与一个固定的集合相匹配(在这种情况下,所有的工作日),并在所有缺失的项目中进行删除,那就太好了,但我已经很感谢第一个了。

这可能吗?

对于第一个和第二个选项?

欢迎任何帮助。提前谢谢。

WPF在XAML中的对象列表中显示字符串数组

问题是将TextBlockText属性绑定到string[]而不是string

内部发生的情况是,WPF在DaysOfWeek字符串数组上调用ToString()方法,结果是"System.string[]".

您想要的是绑定到string.Join("|", DaysOfWeek })

有多种方法可以做到这一点。强烈建议的一种方法是创建一个"视图模型",其中包含您实际想要显示的数据,而不是来自数据库或其他类型模型的数据。

因此,您可以创建一个TimeStampViewModel,它看起来像这样:

public class TimeStampViewModel
{
    public int Id { get; set; }
    public string DaysOfWeek { get; set; }
    public string HoursOfDay { get; set; }
    public TimeStampViewModel(int id, string[] daysOfWeek, string[] hoursOfDay)
    {
        Id = id;
        DaysOfWeek = string.Join("|", daysOfWeek);
        HoursOfDay = string.Join("|", hoursOfDay);
    }
}

然后,您不绑定到TimeStamp对象,而是绑定到在代码隐藏类中创建的TimeStampViewModel对象,如下所示:

TimeStampViewModels = timeStamps
    .Select(x => new TimeStampViewModel(x.Id, x.DaysOfWeek, x.HoursOfDay))
    .ToList();

这假设您的代码背后有一个属性public List<TimeStampViewModel> TimeStampViewModels { get; set; }

如果您想了解更多关于视图模型的一般信息,我建议您阅读模型-视图-视图模型(MVVM)模式。这是微软发布的一篇文章,让你开始学习。MVVM被许多人认为是在WPF(和其他基于XAML的框架)中编程的最佳实践。


要处理你关于三振的"额外积分"问题,这将有点棘手。您需要将视图模型修改为以下内容:

public class TimeStampViewModel
{
    public int Id { get; set; }
    public List<OptionalDayOfWeek> DaysOfWeek { get; set; }
    public string HoursOfDay { get; set; }
    public TimeStampViewModel(int id, string[] daysOfWeek, string[] hoursOfDay)
    {
        Id = id;
        DaysOfWeek = 
            new[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }
            .GroupJoin(daysOfWeek, day => day, dayOfWeek => dayOfWeek, (day, matches) => new OptionalDayOfWeek { DayOfWeek = day, IsAvailable = matches.Any() })
            .ToList();
        HoursOfDay = string.Join("|", hoursOfDay);
    }
}
public class OptionalDayOfWeek
{
    public string DayOfWeek { get; set; }
    public bool IsAvailable { get; set; }
}

同时,XAML需要在类似ItemsControl的内容中显示一周中的几天,其中每个项目都绑定到OptionalDayOfWeek。然后,您可以使用IValueConverter来确定TextDecorations是否应包括Strikethrough。(对不起,我现在没有时间写这部分,但希望这已经足够开始了。)

我基本上同意devuxer的方法。另一方面,如果您希望保留您的模型类,那么解决第二个问题的最简单方法是添加从字符串数组到TextDecorations的转换器。

[ValueConversion(typeof(string[]), typeof(TextDecorations))]
public class DecorationsConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var source = value as string[];
        if (source == null)
            return DependencyProperty.UnsetValue;
        return source.Contains(parameter as string) ? null : TextDecorations.Strikethrough;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

并更改ListView以使用该转换器。

<ListView x:Name="listboxFolder1"  Grid.Row="2" Margin="5" Grid.ColumnSpan="4">
    <ListView.Resources>
        <local:DecorationsConverter x:Key="DecorationsConverterKey"/>
    </ListView.Resources>
    <ListView.ItemTemplate>
        <DataTemplate>
            <Border BorderBrush="Blue" Margin="3" Padding="3" BorderThickness="2" CornerRadius="0 25 0 25" Background="Beige" HorizontalAlignment="Stretch">
                <StackPanel Orientation="Horizontal">
                    <Image Margin="10" Width="50" Height="50" Stretch="Fill" Source="/Images/watch.png">
                        <Image.BitmapEffect>
                            <DropShadowBitmapEffect />
                        </Image.BitmapEffect>
                    </Image>
                    <StackPanel Orientation="Vertical" VerticalAlignment="Center">
                        <TextBlock Text="{Binding ID}"/>
                        <TextBlock>
                            <Run Text="Sunday"
                                 TextDecorations="{Binding DaysOfWeek, Converter={StaticResource DecorationsConverterKey}, ConverterParameter=Sunday}"/>
                            <Run Text="|"/>
                            <Run Text="Monday"
                                 TextDecorations="{Binding DaysOfWeek, Converter={StaticResource DecorationsConverterKey}, ConverterParameter=Monday}"/>
                            <Run Text="|"/>
                            <Run Text="Tuesday"
                                 TextDecorations="{Binding DaysOfWeek, Converter={StaticResource DecorationsConverterKey}, ConverterParameter=Tuesday}"/>
                            <Run Text="|"/>
                            <Run Text="Wednesday"
                                 TextDecorations="{Binding DaysOfWeek, Converter={StaticResource DecorationsConverterKey}, ConverterParameter=Wednesday}"/>
                            <Run Text="|"/>
                            <Run Text="Thursday"
                                 TextDecorations="{Binding DaysOfWeek, Converter={StaticResource DecorationsConverterKey}, ConverterParameter=Thursday}"/>
                            <Run Text="|"/>
                            <Run Text="Friday"
                                 TextDecorations="{Binding DaysOfWeek, Converter={StaticResource DecorationsConverterKey}, ConverterParameter=Friday}"/>
                            <Run Text="|"/>
                            <Run Text="Saturday"
                                 TextDecorations="{Binding DaysOfWeek, Converter={StaticResource DecorationsConverterKey}, ConverterParameter=Saturday}"/>
                        </TextBlock>
                    </StackPanel>
                </StackPanel>
            </Border>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

您希望在TextBlock中将DaysOfWeek显示为文本。DaysOfWeek是一个字符串数组,而不是字符串,因此它不会如您所期望的那样显示。您必须转换为字符串,并且可以在转换函数中指定格式。您必须使用多种方法将字符串数组转换为WPF 中的格式化字符串

第一个解决方案:更好但复杂的方式

public class WeekDaysFormatConverter : System.Windows.Data.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if(value != null && value is string[])
        {
            return string.Join("|", value as string[]);
        }
        return value;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

并应用它:

<Window.Resources>
    <local:WeekDaysFormatConverter x:Key="WeekDaysFormatConverter" />
</Window.Resources>
...
<TextBlock Text="{Binding DaysOfWeek Converter={StaticResource WeekDaysFormatConverter}}"/>

第二个解决方案:只需使用一个属性来指定格式:

public class TimeStamp
{
    public int ID { get; set; }
    public string[] DaysOfWeek { get; set; }
    public string[] HoursOfDay { get; set; }
 public string DaysOfWeekFormatted
    {
        get
        {
            return DaysOfWeek != null ? string.Join("|", DaysOfWeek) : string.Empty;
        }
    }
}

并应用它:

<TextBlock Text="{Binding DaysOfWeekFormatted}"/>

您可以按照如下方式修改类:

public class TimeStamp
    {
        private string _HourList;
        private string _DayList;
        private string[] _DaysOfWeek;
        private string[] _HoursOfDay;
        public string[] HoursOfDay
        {
            get { return _HoursOfDay; }
            set
            {
                _HoursOfDay = value;
                _HourList = String.Join("|", value);
            }
        }
        public int ID { get; set; }
        public string[] DaysOfWeek
        {
            get { return _DaysOfWeek; }
            set
            {
                _DaysOfWeek = value;
                _DayList = String.Join("|", value);
            }
        }
        public string DayLis
        {
            get { return _DayList; }
        }
        public string HourList
        {
            get { return _HourList; }
        }
    }

这样定义类的优点:

只要将值分配给字符串数组DaysOfWeek,它就会自动创建一个字符串DayList,其中所有数组元素ware与分隔符|组合在一起,因为DayList是读取唯一不能为其赋值的属性。您将获得值在绑定时也从该属性

因此,您的xamal加价将如下所示:

 <StackPanel Orientation="Vertical" VerticalAlignment="Center">
      <TextBlock Text="{Binding ID}"/>
      <TextBlock Text="{Binding DayLis}"/>
 </StackPanel>