将集合或数组添加到WPF资源字典

8

我已经搜遍了各种资料,但找不到答案。我有两个问题:

  1. 如何在XAML中创建数组或集合。我有一个数组想放进去并绑定到组合框。我的第一个想法是将一个ItemsControl放入资源字典中,但组合框的ItemsSource需要IEnumerable,所以这个方法行不通。

以下是我在资源字典中尝试过的方法,但都无法实现:

<ItemsControl x:Key="stateList">
    <sys:String>AL</sys:String>
    <sys:String>CA</sys:String>
    <sys:String>CN</sys:String>
</ItemsControl>
<ItemsControl x:Key="stateList2">
    <ComboBoxItem>AL</ComboBoxItem>
    <ComboBoxItem>CA</ComboBoxItem>
    <ComboBoxItem>CN</ComboBoxItem>
</ItemsControl>

以下是我如何绑定它的方法:

<ComboBox SelectedValue="{Binding Path=State}" ItemsSource="{Binding Source={StaticResource stateList2}}"  >

                    </ComboBox>

编辑:已更新

我已经成功地完成了第一部分的工作

 <col:ArrayList x:Key="stateList3">
    <sys:String>AL</sys:String>
    <sys:String>CA</sys:String>
    <sys:String>CN</sys:String>
</col:ArrayList>

然而,我不想使用数组列表,我想使用通用列表,如果有人知道如何做,请告诉我。
编辑更新:我猜XAML对泛型的支持非常有限,所以现在可能最好使用数组列表,但如果有人有答案,我仍然需要第二个问题的帮助。
第二个问题。我尝试在我的XAML中引用合并的资源字典,但遇到了问题,因为在Window.resources下除了字典之外还有其他内容,所以它要求我添加x:Key。一旦我添加了键,系统就无法找到资源字典中的项目。我不得不将合并的字典移动到Grid.Resources中。理想情况下,我想在app.xaml中引用合并的字典,但我遇到了同样的问题。
以下是一些示例代码。如果有多个项,则必须具有键才能编译此第一部分,因为我有转换器,它抱怨每个项都必须有一个键。
<UserControl.Resources>
    <win:BooleanToVisibilityConverter x:Key="VisibilityConverter" />
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/ResourcesD.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

我必须把它改成这样

<UI:BaseStep.Resources>
    <win:BooleanToVisibilityConverter x:Key="VisibilityConverter" />             
</UI:BaseStep.Resources>
<Grid>
    <Grid.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/ResourcesD.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Grid.Resources>
</Grid>

谢谢你

4个回答

19

据我所理解,您想要将ComboBox(或ListBox)绑定到一个项目数组,是吗?如果您想要来自某些外部数据源的项目,可以使用方便的DataContext属性。在MSDN上搜索更多信息。但是,如果您确实需要手动集合,请按照以下方式操作:

创建您自己的类:

public class StringCollection : ObservableCollection<string> { }

现在像这样使用它:

<Window.Resources>
    <local:StringCollection x:Key="stringCollection">
        <sys:String>Hello</sys:String>
        <sys:String>World</sys:String>
    </local:stringCollection>
</Window.Resources>

...

    <ListBox
        Margin="15"
        ItemsSource="{StaticResource stringCollection}" />

或者,如果你想要一个更通用的集合,可以创建一个像这样的类:

public class ObjectCollection : ObservableCollection<object> { }

然后像这样使用它:

    <local:ObjectCollection x:Key="objectCollection">
        <sys:String>Hello</sys:String>
        <TextBlock>World</TextBlock>
        <sys:Int32>12345</sys:Int32>
    </local:ObjectCollection>

    ...

    <ComboBox
        Margin="15"
        ItemsSource="{StaticResource objectCollection}" />



你可能还想利用一些内置类,例如Int32Collection实现了IEnumerable。您可以将它们直接用作资源。


Resources属性(任何FrameworkElement,例如WindowUserControlApplication)的类型是ResourceDictionary而不是资源字典的集合!所以你不能这样做:

<UserControl.Resources>

    <!-- The first RD -->
    <!--<ResourceDictionary>
        <win:BooleanToVisibilityConverter x:Key="VisibilityConverter" />
    </ResourceDictionary>-->

    <!-- Second RD!!! -->
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/ResourcesD.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</UserControl.Resources>

改为这样:

<UserControl.Resources>

    <!-- 
        There should be only 1 main RD, 
        Merge other RDs, if any
     -->
    <ResourceDictionary>

        <!-- First Resource -->
        <win:BooleanToVisibilityConverter x:Key="VisibilityConverter" />

        <!-- Second Resource -->
        <ResourceDictionary.MergedDictionaries>
            <!-- Now, there can be multiple RDs -->
            <ResourceDictionary Source="/ResourcesA.xaml" />
            <ResourceDictionary Source="/ResourcesB.xaml" />
            <ResourceDictionary Source="/ResourcesC.xaml" />
            <ResourceDictionary Source="/ResourcesD.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>

</UserControl.Resources>

希望这可以帮到你。
敬礼,
Mihir Gokani


这是一个有趣的方法。在我的情况下,它不一定需要可观察,但我想它在我的情况下也可以工作。你有解决提供资源键并且解析失败的另一个问题的任何想法吗? - Chris Cap
好的,我已经为你的第二个问题添加了答案。这是你要找的吗? - mg007
糟糕!我觉得我的第二个答案和@Abe的很相似。 - mg007
你有没有想过为什么将一个声明从app.xaml移动到另一个文件夹中的资源字典会引发错误?我已经指定了所有正确的命名空间。 - Chris Cap
你遇到了什么类型的错误?你是否为RD提供了正确的路径?例如“/文件夹名称/我的RD.xaml” - mg007
不要误会,Chris,我认为你应该将这两个问题分开提问,因为它们没有关联。你甚至可以将之前提出的两个问题分开。这样可以简化搜索并避免冗长的答案。 - mg007

1

如果我理解有误,请纠正我,但我认为您想要类似这样的东西?

<Grid.Resources>
  <local:MyCustomCollection x:Key="local:MyCustomCollection"/>
</Brid.Resources>

在你的窗口顶部,你会有一个属性:

xmlns:local="clr-namespace:MyNamespace"

在你的代码中,你会有:

MyCustomCollection  custCol = MyGrid.Resources["MyCustomCollection"] as MyCustomCollection;

绑定将在具有类似以下属性的控件上发生:

ItemsSource="{StaticResource MyCustomCollection}"

不是真的。我想要在资源字典中创建一个集合,因为我想要在多个控件和窗口之间共享该集合。这是一个状态列表。我想要能够将其绑定到状态列表。我不想在代码后台访问它。 - Chris Cap
好的,抱歉我现在不确定,我会保留这个答案以便帮助其他人。 - Brian R. Bondy

1

关于资源,您只需要将额外的转换器移动到新声明的ResourceDictionary中即可:

<App.Resources> 
    <ResourceDictionary> 
        <ResourceDictionary.MergedDictionaries> 
            <ResourceDictionary Source="/ResourcesD.xaml" /> 
        </ResourceDictionary.MergedDictionaries> 

    <win:BooleanToVisibilityConverter x:Key="VisibilityConverter" /> 
    </ResourceDictionary> 
</App.Resources> 

0
如果你将资源字典添加到窗口的资源中,那么你将无法在任何地方访问它,相反,你应该将其添加到“App”的资源中(查看App.xaml文件)。
<App.Resources> 
    <win:BooleanToVisibilityConverter x:Key="VisibilityConverter" /> 
    <ResourceDictionary> 
        <ResourceDictionary.MergedDictionaries> 
            <ResourceDictionary Source="/ResourcesD.xaml" /> 
        </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary> 
</App.Resources> 

无论是否创建任何继承层次结构,此功能将在每个 WPF 对象中都可用。


我确实尝试过那样做,而且那正是我想要的,但它仍然抱怨需要一个资源键,当我添加资源键时,它再也无法解决。 - Chris Cap
我认为你可以将转换器移动到ResourcesD.xaml中,然后你就可以只有一个资源字典元素。 - Akash Kava
嗯,我在app.xaml中还有其他几个资源,我得把它们全部移出来。这样做似乎有些奇怪。我需要用x:key引用绑定它吗? - Chris Cap
不,我认为你不能这样做,我认为最好的方法是,你可以有多个资源字典... 你可以有一个“ConverterResources.xaml”和“CollectionResources.xaml”,并且你可以在资源字典中合并多个资源,然而这样做,你将能够在逻辑上分离一切并解决你的问题。 - Akash Kava
那确实有道理。我尝试了一下,有点奏效。不过,它现在无法创建我在app.xaml中拥有的对象。没有给我任何有价值的调试信息。我稍微改变了一些东西,以便应用程序仍然可以工作。这是一种不太好的解决方案,但资源正在解决中。谢谢。 - Chris Cap

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接