[英]Binding covariance collection WPF
我有:
public class BaseSong
{
public string Artist
{
get; set;
}
public string Title
{
get; set;
}
public class ExtendedSong : BaseSong
{
public string Bitrate { get; set;}
...
}
public class CollectionSong<T> : ObservableCollection<T> where T : BaseSong
{
...
}
public class Playlist
{
CollectionSong _collectionSong;
public CollectionSong<BaseSong> Collection
{
get { return _collectionSong; }
set {...}
}
public Playlist()
{}
...
}
我可以这样
Playlist plist= new Playlist();
plist.Collection = new CollectionSong<BaseSong>();
plist.Collection.Add(new ExtendedSong(){...});
ListView lv = new ListView();
lv.ItemSource = plist.Collection;
但是,如何说关于将listViewItem显示为ExtendedSong而不是BaseSong的ListView?
PS集合仅包含BaseSong项或ExtendedSong
private ListView CreateListView(PlaylistViewModel model)
{
System.Windows.Controls.ListView lv = new System.Windows.Controls.ListView();
lv.SetBinding(ListView.ItemsSourceProperty, new Binding("Collection")
{
Source = model,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
});
lv.SetBinding(ListView.ViewProperty, new Binding("ColumnConfig")
{
Converter = new VkPlayer.Helpers.ConfigToDynamicGridViewConverter()
});
return lv;
}
DataTemplate songLayout = new DataTemplate();
songLayout.DataType = typeof(ExtendedSong);
FrameworkElementFactory spFactory = new FrameworkElementFactory(typeof(TextBlock));
spFactory.Name = "textBoxFactory";
spFactory.SetBinding(TextBlock.TextProperty, new Binding("Bitrate"));
songLayout.VisualTree = spFactory;
ColumnConfig = new ColumnConfig { Columns = new List<Column> {
new Column { Header = "Title", DataField = "FullName" },
new Column { Header = "Bitrate", Template = songLayout}
}
};
public class ConfigToDynamicGridViewConverter : System.Windows.Data.IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var config = value as ColumnConfig;
if (config != null)
{
var grdiView = new GridView();
foreach (var column in config.Columns)
{
var grwCol = new GridViewColumn { Header = column.Header };
if (column.DataField != null)
{
var binding = new System.Windows.Data.Binding(column.DataField);
if (column.Converter != null)
binding.Converter = column.Converter as System.Windows.Data.IValueConverter;
if (column.ConverterParameter != null)
{
binding.ConverterParameter = column.ConverterParameter;
}
grwCol.DisplayMemberBinding = binding;
}
else
{
grwCol.CellTemplate = column.Template;
}
grdiView.Columns.Add(grwCol);
}
return grdiView;
}
return System.Windows.Data.Binding.DoNothing;
}
不起作用,输出:System.Windows.Data错误:40:BindingExpression路径错误:在“对象”“ BaseSong”(HashCode = 23764897)上找不到“ Bitrate”属性
在WPF中,我们使用DataTemplate
来定义数据对象在UI中的外观。 请参阅MSDN上的“ 数据绑定概述”页面,以获取有关数据绑定的更多信息。 因此,我们可以简单地为每种数据类型声明一个DataTemplate
,并且每种DataTemplate
的内容都可以访问该类型的属性。 尝试这样的事情:
<DataTemplate DataType="{x:Type YourPrefix:BaseSong}">
<TextBlock Text="{Binding Title}" />
</DataTemplate>
<DataTemplate DataType="{x:Type YourPrefix:ExtendedSong}">
<TextBlock Text="{Binding Bitrate}" />
</DataTemplate>
...
<ListBox ItemsSource="{Binding CollectionSong" ... />
那就是你要做的。
public class CollectionSong<T> : ObservableCollection<T> where T : BaseSong
{
public CollectionSong<ExtendedSong> ToExSongs() {...}
}
public CollectionSong<BaseSong> CollectionEx
{
get { return Collection.ToExSongs(); }
set {...}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.