環境
準備:
/// アイテム
public partial class MyClass : ObservableRecipient
{
[ObservableProperty]
public string name = string.Empty;
[ObservableProperty]
public string description = string.Empty;
[ObservableProperty]
public int index = -1;
}
/// ViewModel
public class MainViewModel : ObservableRecipient
{
// ## 3 で使う
public bool IsMode
{
get; set;
}
public ObservableCollection<MyClass> MyArray = new();
public MainViewModel()
{
foreach (var item in Enumerable.Range(1, 100))
{
MyArray.Add(item: new MyClass()
{
Name = string.Format("Yamada-{0:000}", item),
Index = item
}); ; ;
}
}
}
1:StyleSelector を使う
/// セレクター
public class MySelector : StyleSelector
{
public Style? Style1
{
get; set;
}
public Style? Style2
{
get; set;
}
protected override Style? SelectStyleCore(object item, DependencyObject container)
{
if (item is MyClass myClass)
{
if (myClass.Index % 2 == 0)
{
return Style1;
}
else
{
return Style2;
}
}
return base.SelectStyleCore(item, container);
}
}
<Page.Resources>
<Style x:Key="MyStyle1" TargetType="ListViewItem">
<Setter Property="Background" Value="AliceBlue" />
</Style>
<Style x:Key="MyStyle2" TargetType="ListViewItem">
<Setter Property="Background" Value="LightYellow" />
</Style>
<views:MySelector
x:Key="MySelectorListview"
Style1="{StaticResource MyStyle1}"
Style2="{StaticResource MyStyle2}" />
</Page.Resources>
<ListView
Grid.Row="1"
ItemContainerStyleSelector="{StaticResource MySelectorListview}"
ItemsSource="{x:Bind Path=ViewModel.MyArray}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="viewmodels:MyClass">
<StackPanel Orientation="Horizontal">
<TextBlock Width="25" Text="{x:Bind Path=Index}" />
<TextBlock Width="150" Text="{x:Bind Path=Name}" />
<TextBlock Text="{x:Bind Path=Description}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
2:DataTemplateSelector を使う
// コレクションの各アイテムのテンプレートを、コレクションの要素によって切り替えるクラス
public class MyTemplateSelector : DataTemplateSelector
{
// テンプレートのプロパティ
public DataTemplate MyTemplate
{
get; set;
}
public DataTemplate DefaultTemplate
{
get; set;
}
// コレクションの要素に応じてテンプレートを選択するメソッド
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
if (item is MyClass myClass)
{
if (myClass.Index % 2 == 0)
{
return DefaultTemplate;
}
else
{
return MyTemplate;
}
}
return DefaultTemplate;
}
}
<DataTemplate x:Key="MyTemp1" x:DataType="viewmodels:MyClass">
<StackPanel Background="AliceBlue" Orientation="Horizontal">
<TextBlock Width="25" Text="{x:Bind Path=Index}" />
<TextBlock Width="150" Text="{x:Bind Path=Name}" />
<TextBlock Text="{x:Bind Path=Description}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="MyTemp2" x:DataType="viewmodels:MyClass">
<StackPanel Background="LightYellow" Orientation="Horizontal">
<TextBlock Width="25" Text="{x:Bind Path=Index}" />
<TextBlock Width="150" Text="{x:Bind Path=Name}" />
<TextBlock Text="{x:Bind Path=Description}" />
</StackPanel>
</DataTemplate>
<views:MyTemplateSelector
x:Key="MyTemplateSelector"
DefaultTemplate="{StaticResource MyTemp1}"
MyTemplate="{StaticResource MyTemp2}" />
<ListView
Grid.Row="1"
ItemTemplateSelector="{StaticResource MyTemplateSelector}"
ItemsSource="{x:Bind Path=ViewModel.MyArray}" />
3: IValueConverter → DataTemplateSelector を使う
動的にセレクターを切り替えたい
public class ModeToSelectorConvertor : IValueConverter
{
public DataTemplateSelector? MySelector
{
get; set;
}
public DataTemplateSelector? DefaultSelector
{
get; set;
}
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is bool iMode)
{
if (iMode)
{
return MySelector;
}
else
{
return DefaultSelector;
}
}
return this.DefaultSelector!;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
<DataTemplate x:Key="MyTemp1" x:DataType="viewmodels:MyClass">
<StackPanel Background="AliceBlue" Orientation="Horizontal">
<TextBlock Width="25" Text="{x:Bind Path=Index}" />
<TextBlock Width="150" Text="{x:Bind Path=Name}" />
<TextBlock Text="{x:Bind Path=Description}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="MyTemp2" x:DataType="viewmodels:MyClass">
<StackPanel Background="LightYellow" Orientation="Horizontal">
<TextBlock Width="25" Text="{x:Bind Path=Index}" />
<TextBlock Width="150" Text="{x:Bind Path=Name}" />
<TextBlock Text="{x:Bind Path=Description}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="MyTemp3" x:DataType="viewmodels:MyClass">
<StackPanel Background="OrangeRed" Orientation="Horizontal">
<TextBlock Width="25" Text="{x:Bind Path=Index}" />
<TextBlock Width="150" Text="{x:Bind Path=Name}" />
<TextBlock Text="{x:Bind Path=Description}" />
</StackPanel>
</DataTemplate>
<views:MyTemplateSelector
x:Key="MyTemplateSelector"
DefaultTemplate="{StaticResource MyTemp1}"
MyTemplate="{StaticResource MyTemp2}" />
<views:MyTemplateSelector
x:Key="MyTemplateSelector2"
DefaultTemplate="{StaticResource MyTemp1}"
MyTemplate="{StaticResource MyTemp3}" />
// コンバーター → セレクター
<views:ModeToSelectorConvertor
x:Key="MyModeToSelectorConvertor"
DefaultSelector="{StaticResource MyTemplateSelector}"
MySelector="{StaticResource MyTemplateSelector2}" />
<ListView
Grid.Row="1"
ItemTemplateSelector="{x:Bind Path=ViewModel.IsMode, Mode=OneWay, Converter={StaticResource MyModeToSelectorConvertor}}"
ItemsSource="{x:Bind Path=ViewModel.MyArray}" />
もう少しスマートな方法がある気がするが…。
以上