添加项目到列表框和样式

本文关键字:样式 列表 项目 添加 | 更新日期: 2023-09-27 18:05:07

我有一个简单的类:

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;        
    }
}

更新:
In 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:


取得了一些进展,只需要知道如何刷新样式(单击按钮后)。加上如果资源不在主窗口。在返回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;
    }
}

添加项目到列表框和样式

我觉得你搞错了,我尽量解释清楚。

首先,你通常不需要改变代码中的样式,比如你的最后一个代码块。一开始很难理解的是ItemContainerStyleDataTemplate的使用。

我建议你这样做。

与其改变ListBoxItem的样式,不如看看使用DataTemplate是否足够。DataTemplate定义了ListBoxItem的Content是如何显示的。

<DataTemplate TargetType="{x:Type Foo}">
 <!-- your visuals and controls here -->
</DataTemplate> 

现在如果你想使用不同的datatemplate你可以使用不同的类并为它们创建不同的datatemplate,或者你使用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中创建模板选择器,并在列表框中引用它

<myNs:FooTemplateSelector x:Key="fooTemplateSelector"/>
<Listbox DataTemplateSelector="{StaticResource fooTemplateSelector}"/>

现在你需要创建2个 DataTemplates appleTemplate *normalTemplate*,你可以很容易地区分使用哪个数据模板的选择器。它会在列表框中自动为你完成。

如果你真的想改变ItemContainer的样式,你可以使用ItemContainerStyleSelector,它的工作原理类似于DataTemplateSelector。但我不建议这么做。只有当你想要修改设计(在本例中是选择颜色等)时,你才应该提供内容并保持ListBoxItem原样,否则它可能会混淆用户或破坏功能。

如果您直接将数据对象添加到ListBox中,则容器项将自动生成,您无法以这种方式获得它们。

使用ItemContainerGenerator:

((ListBoxItem)MyListBox.ItemContainerGenerator.ContainerFromIndex(i)).Style = Resources["MyStyle"] as Style;

为什么不在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事件,你可以使用…已经有一段时间了,我不记得确切的语法了)