为索引属性创建模板

Jas*_*own 3 c# data-binding wpf xaml

我有一个包含一个集合的视图模型,每个集合Item Attributes都包含一个图像的路径.0 .. N集合中的项目属性可能有任何位置.

我视图中的stackpanel包含三个相同的图像控件.每个图像控件都绑定到项目属性图像的路径:

  • 图像控件1绑定到第1项属性的图像路径(在ItemAttributes [0] .Image中找到)
  • 图像控件2绑定到第二项属性的图像路径(在ItemAttributes 1 .Image中找到)
  • 图像控件3绑定到第3项属性的图像路径(在ItemAttributes [2] .Image中找到)

如果有超过3个属性,则忽略它们.为了处理与具有0的可能性- 2个属性(这意味着该图像控制的1个或多个将被绑定到空),这反过来又使在规定错误此篇,我已经添加了一个数据触发器,如下所示:

<DataTrigger Binding="{Binding Attribute1}" Value="{x:Null}">
    <Setter Property="Source" Value="{x:Null}"/>
</DataTrigger>
Run Code Online (Sandbox Code Playgroud)

另外,为了防止索引超出绑定问题,我将视图模型中的项属性拆分为三个属性(我最初返回String.Empty,但将其更改为null以使用数据触发器):

public string Attribute1
{
    get { return _item.Attributes.Count > 0 ? _item.Attributes[0].Image : null; }
}
public string Attribute2
{
    get { return _item.Attributes.Count > 1 ? _item.Attributes[1].Image : null; }
}
 public string Attribute3
{
    get { return _item.Attributes.Count > 2 ? _item.Attributes[2].Image : null; }
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是我希望这个数据触发器适用于所有三个图像属性和相应的图像控件(以及一些其他属性,如宽度,高度,边距等).所以我认为,把它放在一个样式中并将其作为静态资源引用.当我有三个具有不同名称的属性(Attribute1,Attribute2,Attribute3)时,这将不起作用.所以现在我被困在这样做:

<Image>
    <Image.Style>
        <Style TargetType="Image">
            <Setter Property="Source" Value="{Binding Attribute1}" />
            <Setter Property="Width" Value="44" />
            <Setter Property="Height" Value="45" />
            <Setter Property="Margin" Value="5" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding Attribute1}" Value="{x:Null}">
                    <Setter Property="Source" Value="{x:Null}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>
Run Code Online (Sandbox Code Playgroud)

对于其他两个图像控件重复此操作,但Attribute1替换为Attribute2和Attribute3.

所以我想知道是否有办法绑定到集合,例如

<DataTrigger Binding="{Binding Attributes}" Value="{x:Null}">
    <Setter Property="Source" Value="{x:Null}"/>
</DataTrigger>
Run Code Online (Sandbox Code Playgroud)

...然后指定我对模板外部的图像控件绑定感兴趣的索引(我想将参数传递给数据触发器).

任何想法......如果不可能,还有另一种方法吗?

Fed*_*gui 7

<ItemsControl ItemsSource="{Binding Attributes}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Image Source={Binding Something} x:Name=Image/>
            <DataTemplate.Triggers>
                <DataTrigger Binding={Binding Something} Value={x:Null}>
                     <Setter TargetName=Image Property=Source Value={x:Null}/>
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)

在答案中手动输入,而不是真正的XAML.但你应该能够理解我的意思.

编辑:如果您Attributes只是字符串,请"{Binding}"在我放置的任何地方使用"{Binding Something}"

--UPDATE(我会用你的答案更正你的答案更新你的答案) -

<ItemsControl ItemsSource="{Binding Attributes}"
              Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Margin="5">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"
                        HorizontalAlignment="Left" VerticalAlignment="Top" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Image x:Name="Image"
                   Source="{Binding}"
                   Width="45" Height="44" Margin="5" />
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding}" Value="{x:Null}">
                    <Setter TargetName="Image" 
                            Property="Source" Value="{x:Null}" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)

并且将它限制为前三个项属性,这就是我在视图模型的构造函数中所拥有的.Attributes是一个SmartObservableCollection属性(带有和AddRange方法的自定义ObservableCollection以及其他几个好东西),带有_attributes支持字段:

_attributes = new SmartObservableCollection<string>();
var images = from attributes in _item.Attributes
             select attributes.Image;

Attributes.AddRange(images.Take(3));
Run Code Online (Sandbox Code Playgroud)