简体   繁体   English

动态创建控件时,RadioButton上已检查的事件命令绑定不起作用

[英]Checked event command binding on RadioButton doesn't work when the control is dynamically created

I have 3 RadioButton controls that I add to my WPF program dynamically, with the help of a custom class I've defined and an ItemsControl . 在我定义的自定义类和ItemsControl的帮助下,我有3个RadioButton控件可以动态添加到WPF程序中。 My custom class is simple; 我的自定义类很简单; it has two properties, one an identifier and the other a bool to represent the Checked/Unchecked status. 它具有两个属性,一个是标识符,另一个是表示“已Checked/Unchecked状态的bool

public class RadioButtonItem
{
    public string ItemName { get; set; }
    public bool IsChecked { get; set; }
}

I'm using MVVMLight , and a ViewModel , and DataContext etc are all properly setup. 我正在使用MVVMLight ,并且ViewModelDataContext等都已正确设置。

In the MainWindow I have the RadioButton controls added like so: MainWindow我添加了RadioButton控件,如下所示:

<Grid x:Name="LayoutRoot">
    <ItemsControl ItemsSource="{Binding Path=RadioButtons}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"></StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <RadioButton Content="{Binding ItemName}" 
                             IsChecked="{Binding IsChecked}"
                             Margin="12" GroupName="ABC">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="Checked">
                            <i:InvokeCommandAction Command="{Binding RadioButtonCheckedCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </RadioButton>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

Note that i is the Interactivity namespace: xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 请注意, iInteractivity命名空间: xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

Now in my ViewModel , I create a list of RadioButtonItem instances, and at loading time it creates 3 RadioButton controls in the XAML end just fine, as I expect it to. 现在在我的ViewModel ,我创建一个RadioButtonItem实例列表,并在加载时按预期的那样在XAML端创建了3个RadioButton控件。 Then using MVVMLight command RelayCommand , I hook up the Checked event to the RadioButtonCheckedCommand command, which in turn is supposed to call the RadioButtonChecked() private method. 然后使用MVVMLight命令RelayCommand ,将Checked事件连接到RadioButtonCheckedCommand命令,该命令又应该调用RadioButtonChecked()私有方法。

public class MainViewModel : ViewModelBase
{
    private List<RadioButtonItem> _radioButtons;
    public List<RadioButtonItem> RadioButtons
    {
        get => _radioButtons;
        set { _radioButtons = value; RaisePropertyChanged(); }
    }

    public RelayCommand RadioButtonCheckedCommand { get; private set; }

    public MainViewModel()
    {
        RadioButtons = new List<RadioButtonItem>
        {
            new RadioButtonItem() { ItemName = "A", IsChecked = false },
            new RadioButtonItem() { ItemName = "B", IsChecked = false },
            new RadioButtonItem() { ItemName = "C", IsChecked = false },
        };

        RadioButtonCheckedCommand = new RelayCommand(RadioButtonChecked);
    }

    private void RadioButtonChecked()
    {

    }
}

But, when I run the program it doesn't call the said event. 但是,当我运行程序时,它不会调用所述事件。 Neither does it give me any errors. 它也没有给我任何错误。 How do I get an event to work in a dynamically created control like this? 如何使事件在这样动态创建的控件中工作?

To verify my command bindings etc. work, I also created three static RadioButton controls on my window, as shown below, and attached them to the same command and they work fine on Checked event. 为了验证命令绑定等是否正常工作,我还在窗口上创建了三个静态RadioButton控件,如下所示,并将它们附加到同一命令上,并且在Checked事件中可以正常工作。

<StackPanel Grid.Row="1" HorizontalAlignment="Center">
    <RadioButton Content="X" Margin="12">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Checked">
                <i:InvokeCommandAction Command="{Binding RadioButtonCheckedCommand}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </RadioButton>
    <RadioButton Content="Y" Margin="12">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Checked">
                <i:InvokeCommandAction Command="{Binding RadioButtonCheckedCommand}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </RadioButton>
    <RadioButton Content="Z" Margin="12">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Checked">
                <i:InvokeCommandAction Command="{Binding RadioButtonCheckedCommand}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </RadioButton>
</StackPanel>

Previous answer is perfect. 先前的答案是完美的。 Just another solution if you don't want to use elemnt name "LayoutRoot". 如果您不想使用基本名称“ LayoutRoot”,则这是另一个解决方案。

<i:InvokeCommandAction Command="{Binding Path=DataContext.RadioButtonCheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}"/>

inside ItemsControl , binding to RadioButtonCheckedCommand is trying to resolve it against an item - RadioButtonItem instance ItemsControl ,绑定到RadioButtonCheckedCommand的对象正尝试针对某个项目解析它RadioButtonItem实例

but the command is defined in MainViewModel. 但是命令是在MainViewModel中定义的。 it works in the StackPanel because there are no bindings to RadioButtonItems. 它在StackPanel中工作,因为没有对RadioButtonItems的绑定。

the solution is to bind to ItemsControl.DataContext (same as Grid.DataContext): 解决方案是绑定到ItemsControl.DataContext(与Grid.DataContext相同):

<i:InvokeCommandAction Command="{Binding Path=DataContext.RadioButtonCheckedCommand, ElementName=LayoutRoot}"/>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM