【问题标题】:C# WPF Radio Buttons in ListBox using observable collection and Data Template使用可观察集合和数据模板的 ListBox 中的 C# WPF 单选按钮
【发布时间】:2014-10-12 16:38:16
【问题描述】:

我正在使用与 Data Binding Demo (http://code.msdn.microsoft.com/Data-Binding-Demo-82a17c83) 类似的结构制作程序。

我现在正在尝试在我的列表框数据模板中实现单选按钮。我的目标是修改正确 Question 对象的“selected”值。我想可以通过在我的模板中为 2 RadioButton 元素的“Checked”属性提供正确的绑定,但到目前为止我还没有做到这一点。我的另一个尝试是在后面的代码中执行此操作,但我在这里也失败了。谢谢你的建议。

问题类


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.ComponentModel;


namespace WpfApplication1
{
    public class Question : INotifyPropertyChanged
    {
        private int ID;
        private int question_number;
        private string question;
        private bool is_private;
        private bool selected;

        public event PropertyChangedEventHandler PropertyChanged;

        public int _ID
        {
            get { return this.ID; }
            set { this.ID = value; OnPropertyChanged("_ID"); }
        }

        public int _question_number
        {
            get { return this.question_number; }
            set { this.question_number = value; OnPropertyChanged("_question_number"); }
        }

        public string _question
        {
            get { return this.question; }
            set { this.question = value; OnPropertyChanged("_question"); }
        }

        public bool _is_private
        {
            get { return this.is_private; }
            set { this.is_private = value; OnPropertyChanged("_is_private"); }
        }

        public bool _selected
        {
            get { return this.selected; }
            set { this.selected = value; OnPropertyChanged("_selected"); }
        }

        public Question(int ID, int question_number, string question, bool is_private, bool selected)
        {
            this.ID = ID;
            this.question = question;
            this.question_number = question_number;
            this.is_private = is_private;
            this.selected = selected;
        }

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

xaml 文件

<Window x:Class="WpfApplication1.Audyt_window"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Audyt" 
        xmlns:src="clr-namespace:WpfApplication1" 
        ResizeMode="NoResize"
        SizeToContent="WidthAndHeight"
        WindowStartupLocation="CenterScreen"
        >

    <Window.Resources>

        <CollectionViewSource Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Path=Questions}" x:Key="questions_collection" />

        <Style x:Key="text_style" TargetType="TextBlock">
            <Setter Property="Foreground" Value="#333333" />
        </Style>

        <DataTemplate x:Key="Questions_Template" DataType="{x:Type src:Question}">
            <Border BorderThickness="2" BorderBrush="Brown" Padding="7" Name="Question_List_Border" Margin="3" Width="365">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="20"/>
                        <ColumnDefinition Width="30"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="60"/>
                        <ColumnDefinition Width="60"/>
                    </Grid.ColumnDefinitions>

                    <TextBlock Grid.Row="0" Grid.Column="0"
                               Name="textblock_ID"
                               Style="{StaticResource text_style}"
                               Text="ID: "
                               >
                    </TextBlock>
                    <TextBlock Grid.Row="0" Grid.Column="1"
                               Name="textblock2_ID"
                               Style="{StaticResource text_style}"
                               Text="{Binding Path=_ID}"
                               >
                    </TextBlock>
                    <TextBlock Grid.Row="1" Grid.Column="0"
                               Name="textblock_question_number"
                               Style="{StaticResource text_style}"
                               Text="Val"
                               >
                    </TextBlock>
                    <TextBlock Grid.Row="1" Grid.Column="1"
                               Name="textblock2_question_number"
                               Style="{StaticResource text_style}"
                               Text="{Binding Path=_question_number}"
                               >
                    </TextBlock>
                    <TextBlock Grid.Row="0" Grid.Column="2" Grid.RowSpan="3" TextWrapping="Wrap"
                               Name="textblock_question"
                               Style="{StaticResource text_style}"
                               Text="{Binding Path=_question}"
                               >
                    </TextBlock>
                    <RadioButton GroupName="{Binding Path=_ID}" Grid.Row="0" Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Center" Checked="RadioButtons_Yes" Margin="10,17,11,17">Tak</RadioButton>
                    <RadioButton GroupName="{Binding Path=_ID}" Grid.Row="0" Grid.Column="4" HorizontalAlignment="Center" VerticalAlignment="Center" Checked="RadioButtons_No" Margin="10,17,11,17">Nie</RadioButton>
                </Grid>
            </Border>
        </DataTemplate>

    </Window.Resources>

    <Border Padding="10">
        <Grid>

            <ListBox Name="Questions_View_List" HorizontalAlignment="Left" VerticalAlignment="Top" 
                 Height="525" Width="400" Margin="0,0,0,0" BorderThickness="2" BorderBrush="DimGray"
                 ItemsSource="{Binding Source={StaticResource questions_collection}}"  
                 ItemTemplate="{StaticResource Questions_Template}"
                 SelectionMode="Single"
                 SelectedValue="{Binding Path=_ID}" 
                 SelectedValuePath="{Binding Path=_ID}"
                 SelectionChanged="Questions_View_List_SelectionChanged"
                 >
            </ListBox>


        </Grid>
    </Border>
</Window>

背后的代码

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.ComponentModel;


namespace WpfApplication1
{
    public partial class Audyt_window : Window
    {       
        CollectionViewSource questions_collection;

        private ObservableCollection<Question> questions = new ObservableCollection<Question>();
        public ObservableCollection<Question> Questions
        {
            get { return this.questions; }
            set { this.questions = value; }
        }

        public Audyt_window()
        {
            DataContext = this;  
            load_temp_data();
            InitializeComponent();
            questions_collection = (CollectionViewSource)(this.Resources["questions_collection"]);
        }

        private void load_temp_data()
        {
            Question que1 = new Question(1, 2, "Question1", false, false);
            Question que2 = new Question(2, 1, "Question2", false, false);
            Question que3 = new Question(3, 0, "Question3", false, false);
            this.Questions.Add(que1);
            this.Questions.Add(que2);
            this.Questions.Add(que3);
        }

        private void Questions_View_List_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
           // Question question_temp = (Question)((ListBox)e.Source).SelectedValue;

        }

        private void RadioButtons_Yes(object sender, RoutedEventArgs e)
        {
            //Question question_temp = (Question)((ListBox)e.Source(RadioButton)e.Source; // Can't really figure this out ;/ 
            //Variables.selected_question = question_temp._ID;


        }

        private void RadioButtons_No(object sender, RoutedEventArgs e)
        {


        }

    }
}

【问题讨论】:

  • 如果第一个 RadioButton 负责将 _selected 设置为 yes/no,则在其中设置 IsChecked="{Binding _selected, Mode=TwoWay}",两个单选按钮都分配给相同的组名,因此您只能选择其中之一。
  • 谢谢。这实际上是最简单但有效的解决方案。

标签: c# wpf templates listbox radio-button


【解决方案1】:

虽然您的问题仍然有点不清楚,因为与您的百万行代码相比,您只使用了几行字,但我相信我知道您在追求什么。我认为您需要创建一个enum 来区分您的问题的不同答案……也许就这么简单?:

public enum Answer { A, B, C, D ... }

现在您有了enum,您可以在不同的RadioButtons 上使用它以及EnumToBoolConverter

<StackPanel>
    <RadioButton IsChecked="{Binding AnswerProperty, Converter={StaticResource 
        EnumToBoolConverter}, ConverterParameter=A}" Content="Answer A" />
    <RadioButton IsChecked="{Binding AnswerProperty, Converter={StaticResource 
        EnumToBoolConverter}, ConverterParameter=B}" Content="Answer B" />
    <RadioButton IsChecked="{Binding AnswerProperty, Converter={StaticResource 
        EnumToBoolConverter}, ConverterParameter=C}" Content="Answer C" />
    <RadioButton IsChecked="{Binding AnswerProperty, Converter={StaticResource 
        EnumToBoolConverter}, ConverterParameter=D}" Content="Answer D" />
</StackPanel>

这里的AnswerProperty 与您所称的正确问题对象的'selected' 值有关。当然,您现在需要将该属性类型更改为enum 的类型。您可以在网上找到许多不同版本的 EnumToBoolConverter,在 Stack Overflow 上的 How to bind RadioButtons to an enum? 问题的答案中有一个。

【讨论】:

    【解决方案2】:

    试试这个,因为您想在选择 Radio 时更改问题对象

            <RadioButton Command="{Binding RadioCommand}" CommandParameter="Tak" GroupName="MyRadioGroup">Tak</RadioButton>
        <RadioButton Command="{Binding RadioCommand}" CommandParameter="Nie"  GroupName="MyRadioGroup">Nie</RadioButton>
    

    问题.cs

        public class Question : INotifyPropertyChanged
    {
       //your existing code
        //....
        //.....
        //Add Command to your Question class as below
    
        MyCommand radioCommand;
        public MyCommand RadioCommand
        {
            get { return radioCommand ?? (radioCommand = new MyCommand(OnRadioCommand, () => true)); } 
        }
    
        void OnRadioCommand(object obj)
        {
            if (obj != null)
            {
                var checkedRadiochecked = obj.ToString();
                //checkedRadiochecked  will have either Tak or Nie according to 
                //  RadioButton checked
                //do your stuff of changing this object here
            }
        }
    }
    

    }

    Mycommand 或者你可以使用其他类似 Relaycommand 的命令

        public class MyCommand : ICommand
    {
    
        Action<object> executeAction;
        Func<bool> canExecute;
    
        public MyCommand(Action<object> executeAction, Func<bool> canExecute)
        {
            this.executeAction = executeAction;
            this.canExecute = canExecute;
        }
    
        public bool CanExecute(object parameter)
        {
            if (canExecute != null)
                return canExecute();
            else
                return true;
        }
    
        public void RaiseCanExecuteChanged()
        {
            if (CanExecuteChanged != null)  
                CanExecuteChanged(this, new EventArgs());
        }
    
        public event EventHandler CanExecuteChanged;
    
        public void Execute(object parameter)
        {
            if (executeAction != null)
                executeAction(parameter);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-10-06
      • 1970-01-01
      • 1970-01-01
      • 2011-06-08
      • 2014-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-20
      相关资源
      最近更新 更多