我有一个简单的课程:
public class Foo
{
public string Text { get; set; }
public bool AppleStyle { get; set; }
public Foo(string text, bool applyStyle)
{
Text = text;
ApplyStyle = applyStyle;
}
public override string ToString()
{
return Text;
}
}
然后使用它将项目添加到ListBox
:
var one = new Foo("Some Text", false);
var two = new Foo("More Text", true);
MyListBox.Items.Add(one);
MyListBox.Items.Add(two);
然后我遍历ListBox
中的项目以找出如何设置它们的样式。这是我被卡住的地方。我尝试从类ListBoxItem
继承,但如果我这样做,则不会添加任何项目。
for (int i = 0; i < MyListBox.Items.Count; i++)
{
if(((Foo)MyListBox.Items[i]).ApplyStyle)
{
((ListBoxItem)MyListBox.Items[i]).Style = Resources["MyStyle"] as Style;
}
}
更新
在MainWindow.xaml
:
<Window.Resources>
<Style x:Key="MyStyle" TargetType="ListBoxItem">
<Setter Property="Background" Value="Bisque"></Setter>
<Setter Property="FontWeight" Value="Bold"></Setter>
</Style>
</Window.Resources>
更新3:
取得一些进展,只需要知道如何刷新样式(点击按钮后)。如果Resource不在MainWindow.xaml中,那么它会在返回null之前查看App.xaml吗?
MainWindow.xaml
<Window...>
<Window.Resources>
<Style x:Key="MyClass" TargetType="ListBoxItem">
<Setter Property="Background" Value="Bisque"></Setter>
<Setter Property="FontWeight" Value="Bold"></Setter>
</Style>
<myapp:MyListItemStyleSelector x:Key="MyListItemStyleSelector" />
</Window.Resources>
<Grid>
...
<ListBox .... ItemContainerStyleSelector="{StaticResource: MyListItemStyleSelector}" />
...
</Grid>
</Window>
MyListItemStyleSelector.cs
public class MyListItemStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(container);
int index = ic.ItemContainerGenerator.IndexFromContainer(container);
Style applyStyle = null;
var data = item as Foo;
if (data != null && data.ApplyStyle)
{
applyStyle = ic.TryFindResource("MyStyle") as Style;
}
return applyStyle;
}
}
答案 0 :(得分:1)
我认为你在这里有一些混淆,我尽力解释。
首先,您通常不需要更改代码中的样式,就像上一个代码块一样。
一开始很难理解的一件事是使用ItemContainerStyle
和DataTemplate
。
我建议您执行以下操作。
不要改变ListBoxItem的样式,而是看它是否足以使用DataTemplate。 DataTemplate定义了ListBoxItem的内容的显示方式。
<DataTemplate TargetType="{x:Type Foo}">
<!-- your visuals and controls here -->
</DataTemplate>
现在,如果您想使用不同的数据表,您可以使用不同的类并为它们创建不同的DataTemplates,或者使用DataTemplateSelector
public class FooTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
FrameworkElement element = container as FrameworkElement;
var mdl = item as Foo;
if( mdl.AppleStyle )
return element.FindResource("appleTemplate") as DataTemplate;
return element.FindResource("normalTemplate") as DataTemplate;
}
}
在xaml中创建该templateselector并在列表框中引用它
<myNs:FooTemplateSelector x:Key="fooTemplateSelector"/>
<Listbox DataTemplateSelector="{StaticResource fooTemplateSelector}"/>
现在你需要创建2 DataTemplate
s appleTemplate * normalTemplate *,你可以轻松区分哪个数据模板使用vial选择器。这是在ListBox中自动完成的。
如果您真的想要更改ItemContainer的样式,可以使用类似于DataTemplateSelector的ItemContainerStyleSelector。但我不建议。您应该提供内容并保留ListBoxItem,只有当您想要修改设计时(在这种情况下,选择颜色等),否则可能会混淆用户或中断功能。
答案 1 :(得分:0)
如果直接向ListBox
添加数据对象,则会自动生成容器项,您无法以这种方式获取它们。
((ListBoxItem)MyListBox.ItemContainerGenerator.ContainerFromIndex(i)).Style = Resources["MyStyle"] as Style;
答案 2 :(得分:0)
为什么不在XAML中这样做?
<ListBox Name="MyListBox">
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding ApplyStyle}" Value="True">
<Setter Property="Background" Value="Bisque" />
<Setter Property="FontWeight" Value="Bold" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Resources>
</ListBox>
但是你的整体问题是ListBox.Items
返回数据对象的集合,而不是XAML控件。要获取包含数据对象的XAML控件,您必须以H.B.建议并使用MyListBox.ItemContainerGenerator.ContainerFromItem(dataObject)
获取数据对象的XAML容器。只要确保你等到ItemContainerGenerator完成渲染项目以获取容器之后(我相信它有一个Status
属性或StatusChanged
事件你可以使用......它已经有一段时间我可以'记住确切的语法)