WPF RadioButtons详细信息UserControl在导航通过父ListView时未选中

时间:2013-11-20 14:34:40

标签: wpf

---编辑包含完整的代码示例---

我知道.NET 3.5 RadioButton存在很多问题,但我相信这是一个不同的问题,我在搜索中没有找到任何东西。我已经整理了一个非常小的代码示例来演示我正在观察的问题。

我的XAML中有一个ListView,它的SelectedItem绑定到我的ViewModel中的SelectedModel。这个相同的XAML包含一个StackPanel,它在浏览ListView中的项目时显示SelectedModel的RadioButton选项。一切都很好,直到我将一个RadioButton组添加到混合中。现在,如果我在ListView中选择了一个已选中其中一个RadioButton选项的记录,那么在ListView中选择另一个选中了不同选项的记录,现在再次选择ListView中的上一条记录,所有的RadioButtons都是ListView项目将被取消选中。如果我在ListView中上下移动足够长的时间,则每个RadioButton和基础布尔值都将设置为false。

型号代码:

 public class Model
 {
    public string Name { get; set; }
    public bool IsOne { get; set; }
    public bool IsTwo { get; set; }
    public bool IsThree { get; set; }
 }

ViewModel代码:

public class ViewModel: INotifyPropertyChanged
{
    private Model _selectedModel;
    public event PropertyChangedEventHandler PropertyChanged;
    public List<Model> ModelList { get; set; }

    public Model SelectedModel
    {
        get { return _selectedModel; }
        set
        {
            _selectedModel = value;
            OnPropertyChanged("SelectedModel");
        }
    }

    public ViewModel()
    {
        ModelList = new List<Model>();
        ModelList.Add(new Model() {Name = "Florida"});
        ModelList.Add(new Model() {Name = "Texas"});
        ModelList.Add(new Model() {Name = "Arizona"});
        ModelList.Add(new Model() {Name = "Washington"});
    }

    void OnPropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(
                    this, new PropertyChangedEventArgs(propName));
    }
}

最后,XAML代码:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100"/>
        <ColumnDefinition />

    </Grid.ColumnDefinitions>
    <ListView ItemsSource="{Binding Path=ModelList}" 
              SelectedItem = "{Binding SelectedModel}"  
              DisplayMemberPath="Model">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Name" 
                                DisplayMemberBinding="{Binding Name}" 
                                Width="100"/>
            </GridView>
        </ListView.View>
    </ListView>
    <StackPanel Grid.Column="1">
        <RadioButton x:Name="IsOne" Content="One" Margin="3" 
                     IsChecked="{Binding Path=SelectedModel.IsOne}" 
                     GroupName="{Binding Path=SelectedModel.Name}"/>
        <RadioButton x:Name="IsTwo" Content="Two" Margin="3" 
                     IsChecked="{Binding Path=SelectedModel.IsTwo}"  
                     GroupName="{Binding Path=SelectedModel.Name}" />
        <RadioButton x:Name="IsThree" Content="Three" Margin="3" 
                     IsChecked="{Binding Path=SelectedModel.IsThree}" 
                     GroupName="{Binding Path=SelectedModel.Name}" />
    </StackPanel>
</Grid>

关于什么会导致绑定以这种方式表现的想法?

谢谢,

格伦

2 个答案:

答案 0 :(得分:1)

如果RadioButton的每一行都有ListView个{},则需要为每个GroupName中的RadioButton提供唯一GridView个行。我知道如何执行此操作的唯一方法是向Bind中显示的数据类型类添加额外属性。只要集合中的每个项具有不同的值,那么该值是什么并不重要。

然后,您可以GroupName将新项目属性设置为集合中每个RadioButton的{​​{1}}属性:

<StackPanel>
    <RadioButton Content="Demo" GroupName="{Binding GroupName}" ... />
    <RadioButton Content="Screener" GroupName="{Binding GroupName}" ... />
    <RadioButton Content="Vote" GroupName="{Binding GroupName}" ... />
    <RadioButton Content="Vote Follow Up" GroupName="{Binding GroupName}" ... />
    <RadioButton Content="Named Vote" GroupName="{Binding GroupName}" ... />
</StackPanel>

我发现了一篇很好地展示XAML示例的文章:

Grouped RadioButton for WPF Datagrid


更新&gt;&gt;&gt;

是的,在您的情况下,当您在某种容器面板中有一组RadioButton时,您甚至不需要提供GroupName,因为框架会为我们提供Binding '掩护下'。我重构了你的XAML以使用不同的<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="100"/> <ColumnDefinition /> </Grid.ColumnDefinitions> <ListView ItemsSource="{Binding ModelList}" IsSynchronizedWithCurrentItem="True" SelectedItem="{Binding SelectedModel}" DisplayMemberPath="Model"> <ListView.View> <GridView> <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="100"/> </GridView> </ListView.View> </ListView> <StackPanel Grid.Column="1"> <RadioButton x:Name="IsOne" Content="One" Margin="3" IsChecked="{Binding ModelList/IsOne}" /> <RadioButton x:Name="IsTwo" Content="Two" Margin="3" IsChecked="{Binding ModelList/IsTwo}" /> <RadioButton x:Name="IsThree" Content="Three" Margin="3" IsChecked="{Binding ModelList/IsThree}" /> </StackPanel> </Grid> 来查看是否有任何区别,但事实并非如此。你在那里发现了一个骨头怪物。这是我结束的XAML仍然表现出同样的问题:

CheckBox

我在您的问题中删除了代码示例中未使用的属性。我还建议您使用更准确的问题描述编辑您的问题...虽然我没有完全解决取消选中RadioButton所需的点击模式,但我可以看到它与第三个{{1}}无关。它当然也发生在其他两个上。

可能值得将此报告为Microsoft Connect website上的错误...也许已经有解释或解决方法了吗?

答案 1 :(得分:1)

我已经确认这是一个已经存在的问题,一直持续到Framework 4.5。 Franklin Chen为我提供了一个很好的小解决方案,扩展了RadioButton类。

以下是指向answer的链接。

这是他的代码。现在只需绑定到IsCheckedReal属性,一切正常。

public class RadioButtonExtended : RadioButton
{
    static bool m_bIsChanging = false;

    public RadioButtonExtended()
    {
        this.Checked += new RoutedEventHandler(RadioButtonExtended_Checked);
        this.Unchecked += new RoutedEventHandler(RadioButtonExtended_Unchecked);
    }

    void RadioButtonExtended_Unchecked(object sender, RoutedEventArgs e)
    {
        if (!m_bIsChanging)
            this.IsCheckedReal = false;
    }

    void RadioButtonExtended_Checked(object sender, RoutedEventArgs e)
    {
        if (!m_bIsChanging)
            this.IsCheckedReal = true;
    }

    public bool? IsCheckedReal
    {
        get { return (bool?)GetValue(IsCheckedRealProperty); }
        set
        {
            SetValue(IsCheckedRealProperty, value);
        }
    }

    // Using a DependencyProperty as the backing store for IsCheckedReal. This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsCheckedRealProperty =
    DependencyProperty.Register("IsCheckedReal", typeof(bool?), typeof(RadioButtonExtended),
    new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Journal |
    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
    IsCheckedRealChanged));

    public static void IsCheckedRealChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        m_bIsChanging = true;
        ((RadioButtonExtended)d).IsChecked = (bool)e.NewValue;
        m_bIsChanging = false;
    }
}