无法在动态单选按钮单击中添加组合框中的不同项目

时间:2012-11-03 10:51:08

标签: c# wpf xaml dynamic mvvm

我正在使用我的wpf应用程序中的radiobuttons和combobox。虽然我是C ++开发人员,但最近我转到了C#。我的应用程序处理动态生成上述组件。基本上我已经在我的应用程序中创建了4个动态单选按钮,并且在点击每个按钮时,我应该在我的组合框中添加不同的项目。这是代码:

XAML:

<ItemsControl ItemsSource="{Binding Children}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Vertical" >
                        <RadioButton Content="{Binding RadioBase}"  Margin="0,10,0,0"  IsChecked="{Binding BaseCheck}" GroupName="SlotGroup"  Height="15" Width="80" HorizontalAlignment="Center" VerticalAlignment="Center"/>                            
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

<ComboBox Visibility="{Binding IsRegisterItemsVisible}" ItemsSource="{Binding RegComboList}" SelectedItem="{Binding SelectedRegComboList, Mode=TwoWay}" SelectedIndex="0" />

FPGARadioWidgetViewModel类:

public ObservableCollection<FPGAViewModel> Children { get; set; }

    public FPGARadioWidgetViewModel()
    {
        Children = new ObservableCollection<FPGAViewModel>();
        Children.Add(new FPGAViewModel() { RadioBase = "Base 0x0", ID = 0 });
        Children.Add(new FPGAViewModel() { RadioBase = "Base 0x40", ID = 1 });
        Children.Add(new FPGAViewModel() { RadioBase = "Base 0x80", ID = 2 });
        Children.Add(new FPGAViewModel() { RadioBase = "Base 0xc0", ID = 3 });            
    }

FPGAViewModel类:

private bool sBaseCheck;
    public bool BaseCheck
    {
        get { return this.sBaseCheck; }
        set
        {
            this.sBaseCheck = value;                
            AddComboItems();
            this.OnPropertyChanged("BaseCheck");
        }
    }    

private ObservableCollection<string> _RegComboList;
    public ObservableCollection<string> RegComboList
    {
        get { return _RegComboList; }
        set
        {
            _RegComboList = value;
            OnPropertyChanged("RegComboList");
        }
    }        

private void AddComboItems()
    {
        int baseRegister = 0x40 * ID;
        ObservableCollection<string> combo = new ObservableCollection<string>();            

        for (int i = 0; i < 0x40; i++)
        {
            int reg = (i * 8) + baseRegister;
            combo[i] = "0x" + reg.ToString("X");
        }

        RegComboList = new ObservableCollection<String>(combo);
        OnPropertyChanged("RegComboList");
    }


private bool isRegisterItemsVisible = false;
    public bool IsRegisterItemsVisible
    {
        get { return isRegisterItemsVisible; }
        set
        {
            isRegisterItemsVisible = value;
            OnPropertyChanged("IsRegisterItemsVisible");                
            OnPropertyChanged("RegComboList");
        }
    }

如果您注意到,在单击特定单选按钮时,它应根据ID在组合框中添加具有不同值的项目。必须确保在点击任何单选按钮时,只应添加其中的项目,并且应清除组合框的先前内容。我正在尝试使用上面的代码做同样的事情,但是当我调试时,似乎没有任何东西出现在组合框中。

请帮忙:)

2 个答案:

答案 0 :(得分:2)

我会将ComboBox的ItemsSource与选定的RadioButton相关联。从您现有的模型中,我会让每个FPGAViewModel都有ObservableCollection<string>您已完成的任务。然后,正如Alex Curtis所说,您将在所选单选按钮和组合框的ItemsSource之间创建绑定。

查看this帖子,通过更改ItemsControl以使用现有DataTemplate的ListBox,可能更容易获得所选单选按钮。然后,您可以将IsChecked属性绑定到ListBoxItem.IsSelected。

           <ListBox ItemsSource="{Binding Children}" SelectedItem="{Binding YourSelectedItem}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical" >
                            <RadioButton Content="{Binding RadioBase}"  Margin="0,10,0,0"  GroupName="SlotGroup"  Height="15" Width="80" HorizontalAlignment="Center" VerticalAlignment="Center">
                                <RadioButton.IsChecked>
                                    <Binding Path="IsSelected"
                                     RelativeSource="{RelativeSource AncestorType=ListBoxItem}" Mode="TwoWay" />
                                </RadioButton.IsChecked>
                            </RadioButton>                            
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>


<ComboBox Visibility="{Binding YourSelectedItem.IsRegisterItemsVisible}" ItemsSource="{Binding YourSelectedItem.RegComboList}" SelectedItem="{Binding YourSelectedItem.SelectedRegComboList, Mode=TwoWay}" SelectedIndex="0" />

然后在包含Children集合的ViewModel中,您需要有一个:

    private FPGAViewModel _yourSelectedItem;

    public FPGAViewModel YourSelectedItem
    {
        get { return _yourSelectedItem; }
        set { _yourSelectedItem = value;
        OnPropertyChanged("YourSelectedItem");}
    }

要填充您的项目,我会更改FPGAViewModel的构造函数以接受Base和ID作为参数,以便您可以在构造函数中调用AddComboItems()

public FPGAViewModel(string radioBase, int id)
{
    RadioBase = radioBase;
    ID = id;
    AddComboItems();
}

现在

Children.Add(new FPGAViewModel() { RadioBase = "Base 0x0", ID = 0 });

应该成为

Children.Add(new FPGAViewModel("Base 0x0", 0));

答案 1 :(得分:1)

这是因为组合框已被绑定到不同的字符串引用。每次无线电单击都会更改项目,并返回对列表的引用。尝试重新使用当前的RegComboList,删除其中的现有项目,然后添加新项目。如果无法更新组合框,请以两种方式绑定到RegComboList。

编辑:这是一个工作示例.Net 4.5,不要担心概念是一样的。

这里的组合框最初加载了5个单词。然后,每次用户单击该按钮时,都会将一组新单词放入列表中,从而更改组合框。 请注意清楚完成的收集。

图片是在最初的“Lorem Ipsum”加载之后...

2nd Run where it is past the Lorem Ipsum

<Window x:Class="WPFCombo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50*" />
            <RowDefinition Height="50*" />
            <RowDefinition Height="172*" />
        </Grid.RowDefinitions>
        <Button Content="Button"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Width="75"
                Click="Button_Click_1" />
        <ComboBox HorizontalAlignment="Center"
                  Grid.Row="1"
                  ItemsSource="{Binding RegComboList}"
                  VerticalAlignment="Center"
                  Width="120" />
    </Grid>
</Window>

背后的代码

public partial class MainWindow : Window,  INotifyPropertyChanged
{
    private const string cLorem = @"Lorem ipsum dolor sit amet consectetur adipiscing elit Maecenas
                                   et lacinia nisl Aenean nec aliquet risus Phasellus dui purus 
                                   sollicitudin nec cursus vitae cursus id purus Nam quis risus 
                                   velit Sed aliquam tellus in odio pulvinar tincidunt Sed bibendum mi";



    private int Skip { get; set; }
    private ObservableCollection<string> _RegComboList;
    public event PropertyChangedEventHandler PropertyChanged;

    public ObservableCollection<string> RegComboList
    {
        get { return _RegComboList; }
        set
        {
            _RegComboList = value;
            OnPropertyChanged();
        }
    }


    public MainWindow()
    {
        InitializeComponent();
        RegComboList = new ObservableCollection<string>();
        GenerateWords(5);

        DataContext = this;
    }

    private void GenerateWords(int toTake)
    {
        RegComboList.Clear();

        Regex.Split(cLorem, @"\s+").Skip(Skip)
             .Take(toTake)
             .ToList()
             .ForEach(word => RegComboList.Add( word ));

        Skip += toTake;

    }

    protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = "" )
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler( this, new PropertyChangedEventArgs( propertyName ) );
        }
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        GenerateWords(new Random().Next(1, 10));
    } 
}