在 DataTemplate UWP 中绑定 ComboBoxItem 的 IsSelected 属性

Binding the IsSelected property of ComboBoxItem in DataTemplate UWP

我正在尝试绑定 ComboBoxItem 的 属性 IsSelected 以显示正确的图标,如果选择了项目,则应显示红色图标,否则打开列表的其余部分为灰色。下面的代码显示了我如何尝试实现该功能的方式。

<ComboBox
    ItemsSource="{Binding Icons}"
    SelectedItem="{Binding SelectedIcon, Mode=TwoWay}"
    Style="{ThemeResource DefaultComboBoxStyle}"
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                    <Image
                        Width="20"
                        Height="20"
                        Source="{Binding IconId, Mode=TwoWay, Converter={StaticResource IconConverter}, ConverterParameter={StaticResource True}}"
                        Visibility="{Binding Path=IsSelected,RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BoolToVisibilityConverter}}" />
                    <Image
                        Width="20"
                        Height="20"
                        Source="{Binding IconId, Mode=TwoWay, Converter={StaticResource IconConverter}}"
                        Visibility="{{Binding Path=IsSelected,RelativeSource={RelativeSource Mode=TemplatedParent} Converter={StaticResource BoolToVisibilityInverted}}" />
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

两个图像转换器的项目图标 ID 相同,转换器将 return 根据传递的参数更正图像 link。我试图获取父数据上下文并尝试使用 IsSelected 属性 of comboBoxItem (SelectorItem) 但它不起作用。

我不想在我迭代的 ViewModel 中添加 IsSlected 属性,我假设存在一些语法但我找不到它。我只想获取 属性 IsSelected 的值并绑定到 xaml 而无需更改 ViewModel 中的代码。

实现了类似于下面代码中的内容,但对元素进行了硬编码。根据 IsSelected 项目 属性 显示 ComboBoxItem 正确的图标。我想要使​​用 ItemsSource 和 DataTemplate 的相同功能。

 <ComboBox
    SelectedIndex="{Binding IconType, Mode=TwoWay, Converter={StaticResource IconTypeIndexToIconConverter}}"
    Style="{ThemeResource DefaultComboBoxStyle}">
    <ComboBoxItem x:Name="SwitchIcon">
        <StackPanel Orientation="Horizontal">
                <Image
                    Source="{Binding Source=1, Converter={StaticResource IconConverter}}"
                    Style="{ThemeResource DeviceTypeImageBlockStyle}"
                    Visibility="{Binding IsSelected, ElementName=SwitchIcon, Converter={StaticResource BoolToVisibilityInverted}}" />
                <Image
                    Source="{Binding Source=1, Converter={StaticResource IconConverter}, ConverterParameter={StaticResource True}}"
                    Style="{ThemeResource DeviceTypeImageBlockStyle}"
                    Visibility="{Binding IsSelected, ElementName=SwitchIcon, Converter={StaticResource BoolToVisibilityConverter}}" />
        </StackPanel>
    </ComboBoxItem>
    <ComboBoxItem x:Name="LightDimmingIcon">
        <StackPanel Orientation="Horizontal">
                <Image
                    Source="{Binding Source=2, Converter={StaticResource IconConverter}}"
                    Style="{ThemeResource DeviceTypeImageBlockStyle}"
                    Visibility="{Binding IsSelected, ElementName=LightDimmingIcon, Converter={StaticResource BoolToVisibilityInverted}}" />
                <Image
                    Source="{Binding Source=2, Converter={StaticResource IconConverter}, ConverterParameter={StaticResource True}}"
                    Style="{ThemeResource DeviceTypeImageBlockStyle}"
                    Visibility="{Binding IsSelected, ElementName=LightDimmingIcon, Converter={StaticResource BoolToVisibilityConverter}}" />
        </StackPanel>
    </ComboBoxItem>
</ComboBox>

有什么想法吗?解决方案?

Binding the IsSelected property of ComboBoxItem in DataTemplate UWP

恐怕你无法在 DataTemplate UWP 中绑定 ComboBoxItemIsSelected 属性。因为TemplatedParent RelativeSource是ContentPresenter而不是ComboBoxItem,你可以用下面的xaml来验证。

<ComboBox.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal">
            <Border DataContext="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}}">
                <TextBlock x:Name="Print" Text="{Binding}"/>
            </Border>
            <TextBlock Text="{Binding}" />
        </StackPanel>
    </DataTemplate>
</ComboBox.ItemTemplate>

它将在 Print 文本块中显示 Windows.UI.Controls.ContentPresenter

I don't want to add IsSlected property in ViewModel through which I iterate, I assume that some syntax exists but I couldn't find it.

一般情况下,我们通过将IsSlected添加到模型class中来处理场景。并获取 select 项修改 IsSlected 值以生效 UI。我在下面制作了完整的示例。

代码隐藏

public sealed partial class MainPage : Page, INotifyPropertyChanged
{
    public List<CBContent> Items { get; set; } = new List<CBContent>();
    public MainPage()
    {
        this.InitializeComponent();
        Items.Add(new CBContent { Content = "Item1", IsSelected = false });
        Items.Add(new CBContent { Content = "Item2", IsSelected = false });
        Items.Add(new CBContent { Content = "Item3", IsSelected = false });
        Items.Add(new CBContent { Content = "Item4", IsSelected = false });
        Items.Add(new CBContent { Content = "Item5", IsSelected = false });
        Items.Add(new CBContent { Content = "Item6", IsSelected = false });
        this.DataContext = this;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    private CBContent _selectItem;

    private CBContent _previousSelectItem;
    public CBContent SelectItem
    {
        get
        {
            return _selectItem;
        }
        set
        {
            _selectItem = value;              
            value.IsSelected = true;
            if(_previousSelectItem != null)
            {
                _previousSelectItem.IsSelected = false;
            }
            _previousSelectItem = _selectItem;
            OnPropertyChanged();               
        }
    }
}
public class CBContent : INotifyPropertyChanged
{
    public string Content { get; set; }
    private bool _isSelect;
    public bool IsSelected
    {
        get
        {
            return _isSelect;
        }
        set
        {
            _isSelect = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Xaml

<Grid>
    <ComboBox ItemsSource="{Binding Items, Mode=OneWay}" SelectedItem="{Binding SelectItem,Mode=TwoWay}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">

                    <Rectangle
                        Width="20"
                        Height="20"
                        Fill="Red"
                        Visibility="{Binding IsSelected, Mode=TwoWay}"
                        />
                    <TextBlock Text="{Binding Content}" />
                </StackPanel>

            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
</Grid>