将项添加到ListBox和Style

时间:2011-08-11 11:52:20

标签: c# wpf xaml controls listbox

我有一个简单的课程:

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

3 个答案:

答案 0 :(得分:1)

我认为你在这里有一些混淆,我尽力解释。

首先,您通常不需要更改代码中的样式,就像上一个代码块一样。 一开始很难理解的一件事是使用ItemContainerStyleDataTemplate

我建议您执行以下操作。

不要改变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添加数据对象,则会自动生成容器项,您无法以这种方式获取它们。

使用ItemContainerGenerator

((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事件你可以使用......它已经有一段时间我可以'记住确切的语法)