我是WPF的新手,仍在使用绑定等等,所以这可能是一个基本问题。
考虑以下课程:
class DataHolder
{
public List<int> Data;
// Points to one of the items in Data. Thus can be between 0 and Data.Count
public int Pointer;
}
我已将ListBox的DataContext设置为上面类的实例,其ItemSource是实例的“数据”。
现在我想在ListBox中标记包含数据[指针] 的列表项的颜色为灰色。
我应该使用什么?我已尝试使用DataTriggers,但我不确定如何使用它们比较两个不同的值。我不想在此时使用IValueConverter,除非不可能这样做。
编辑:随意将公开数据转换为上述类中的属性
谢谢!
答案 0 :(得分:2)
我之前通过创建我称之为DataViewModel的方式完成了这样的事情。这基本上是集合中每个项目的ViewModel。我用你的例子快速尝试了它并且它有效。我会在下面粘贴我的所有代码,如果你愿意,应该能够将其拉入并执行它。
<强> MainWindow.xaml 强>
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindow_ViewModel/>
</Window.DataContext>
<StackPanel>
<TextBox Text="{Binding Pointer, Mode=TwoWay}" Height="20" Width="100"/>
<ListBox ItemsSource="{Binding MyDataHolder}" Height="20" Width="100">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}" Background="{Binding Color}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<强> MainWindow_ViewModel.cs 强>
public class MainWindow_ViewModel
{
public MainWindow_ViewModel()
{
data = new DataHolder();
foreach (int value in data.Data)
{
myData.Add(new Data_DataViewModel() { Value = value });
}
this.Pointer = 4;
}
private DataHolder data;
private List<Data_DataViewModel> myData = new List<Data_DataViewModel>();
public List<Data_DataViewModel> MyDataHolder
{
get
{
return myData;
}
}
public int Pointer
{
get { return this.data.Pointer; }
set
{
this.data.Pointer = value;
foreach (Data_DataViewModel dvm in this.myData)
{
dvm.UpdateColor(this.data.Pointer);
}
}
}
}
<强> DataHolder.cs 强>
public class DataHolder
{
public List<int> Data
{
get { return data; }
}
private List<int> data = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8 };
public int Pointer = 3;
}
<强> Data_DataViewModel.cs 强>
public class Data_DataViewModel : INotifyPropertyChanged
{
public int Value
{
get { return val; }
set { val = value; }
}
private int val;
public Brush Color
{
get
{
if (this.Value == pointer)
{
return Brushes.Gray;
}
else
{
return Brushes.Pink;
}
}
}
private int pointer;
public void UpdateColor(int pointerValue)
{
this.pointer = pointerValue;
OnPropertyChanged("Color");
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
答案 1 :(得分:1)
有趣的问题。我的解决方案使用ItemTemplateSelector。在其SelectTemplate覆盖中,您可以访问ListItems所在的Panel(VirtualizingStackPanel)。这里的技巧是,当每个ListItem被添加到ListBox时,会调用此覆盖,我们可以使用ChildCount在ListBox中确定其索引。这有助于我们进行比较并选择正确的模板。
<强> Main.xaml 强>
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApplication1" mc:Ignorable="d" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate
x:Key="DataTemplateWithHighlight">
<StackPanel>
<TextBlock HorizontalAlignment="Stretch"
Text="{Binding Mode=OneWay}"
Background="Gray" />
</StackPanel>
</DataTemplate>
<DataTemplate
x:Key="DataTemplateWithoutHighlight">
<StackPanel>
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding Mode=OneWay}"
Background="White" />
</StackPanel>
</DataTemplate>
<local:ListBoxItemTemplateSelector
x:Key="listBoxItemTemplateSelector"
HighlightedItemTemplate="{StaticResource DataTemplateWithHighlight}"
NonHighlightedItemTemplate="{StaticResource DataTemplateWithoutHighlight}" />
</Window.Resources>
<StackPanel Orientation="Vertical" d:LayoutOverrides="Height" HorizontalAlignment="Center" VerticalAlignment="Center">
<ListBox
x:Name="listBoxWithMeaninglessNumbers"
Height="100"
Width="100"
ItemsSource="{Binding Data}"
ItemTemplateSelector="{DynamicResource listBoxItemTemplateSelector}">
</ListBox>
</StackPanel>
</Window>
DataItems类
public class DataItems
{
public List<int> Data { get; set;}
public int HighlightedIndex { get; set; }
}
一些初步数据让你前进
public static class DataStub
{
public static DataItems TestDataItems
{
get
{
var dataItems = new DataItems();
dataItems.Data = new List<int>(){1,5,9,6,8};
dataItems.HighlightedIndex = 2;
return dataItems;
}
}
}
<强> MainWindow.Xaml.cs 强>
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
listBoxWithMeaninglessNumbers.DataContext = DataStub.TestDataItems;
}
}
TemplateSelector类:
public class ListBoxItemTemplateSelector:DataTemplateSelector
{
public DataTemplate NonHighlightedItemTemplate { get; set; }
public DataTemplate HighlightedItemTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var listBoxItem = ((FrameworkElement) container).TemplatedParent as ListBoxItem;
var panel = VisualTreeHelper.GetParent(listBoxItem) as Panel;
var highlightedIndex = (panel.DataContext as DataItems).HighlightedIndex;
var currentChildIndex = panel.Children.Count-1;
return (highlightedIndex == currentChildIndex) ? HighlightedItemTemplate : NonHighlightedItemTemplate;
}
}
}
希望这有帮助。
答案 2 :(得分:1)
列表框还有一个可以绑定的SelectedIndex属性。使索引成为ViewModel上的属性(提示:数据属性,同时确保该属性触发notify change event)。然后编辑列表框项的Selected State。
IMO比其他提案容易得多,并且适当地使用了模板和绑定 more 。