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。
我希望它像"星期一|星期五|星期天"。
如果有可能将其与一个固定的集合相匹配(在这种情况下,所有的工作日),并在所有缺失的项目中进行删除,那就太好了,但我已经很感谢第一个了。
这可能吗?
对于第一个和第二个选项?
欢迎任何帮助。提前谢谢。
问题是将TextBlock
的Text
属性绑定到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>