1

我正在我的 wpf 应用程序中处理单选按钮和组合框。虽然我是一名 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 在组合框中添加具有不同值的项目。必须确保在单击任何单选按钮时,仅应添加该项目,并且应清除组合框的先前内容。我正在尝试使用上面的代码做同样的事情,但是当我调试时,组合框中似乎没有出现任何内容。

请帮忙 :)

4

2 回答 2

2

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

看看这篇文章,通过将 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));
于 2012-11-05T03:06:20.717 回答
1

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

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

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

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

第二次运行,它经过 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));
    } 
}
于 2012-11-03T11:09:17.970 回答