ComboBox在应用程序启动时锁定

时间:2011-05-05 16:06:46

标签: c# wpf combobox

好的,这是一个奇怪的(或者我做的事情很愚蠢)。 我有一个WPF组合框,在表单加载(app start)上填充了一个字符串数组。 这部分工作正常。当我试图改变所述组合框内的任何信息时,粘性位。调试说它正在改变,但没有任何东西在视觉上显示。

// Populate the combobox:
private void ComboBlocks()
{
    comboBox1.Items.Clear();
    string[,] _tmp = _kits.BlockIDNames;
    string[] _tmp1 = new string[_tmp.GetLength(0)];

    for (int i = 0; i < _tmp.GetLength(0); i++)
    {
        _tmp1[i] = _tmp[i, 0] + " - " + _tmp[i, 1];
    }

    foreach (string s in _tmp1)
    {
        string[] _tmpS1 = s.Split(new char[] { '-' });
        int _tmpS2 = Convert.ToInt32(_tmpS1[0].Trim());
        bool _banneditem = _cbi.BannedItemExists(_tmpS2);
        if (_banneditem == true)
            AddComboItem(s, true);
        else
            AddComboItem(s);
    }

    if (comboBox1.Items.Count > 0)
        comboBox1.SelectedIndex = 0;            
}

// Add item to combobox:
private void AddComboItem(string _text,bool _redtext = false)
{
    Grid grid = new Grid();
    grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });

    TextBlock text = new TextBlock();
    text.Text = _text;

    if (_redtext == true)
        text.Foreground = Brushes.Red;
    else
        text.Foreground = Brushes.Black;

    grid.Children.Add(text);
    Grid.SetColumn(text, 0);

    ComboBoxItem comboBoxItem = new ComboBoxItem();
    comboBoxItem.Content = grid;
    comboBoxItem.Tag = _text;

    comboBox1.Items.Add(comboBoxItem);
}

另外,我对C#相当新,所以如果有什么我做错了/效率低下,请指出。

非常感谢。

编辑:迭代每一个并更改文本值可能与从另一个数组获取其信息一样多。它必须检查数组中的每个项目,如果它存在,将其着色为红色,如果不是,则将其着色为黑色。

1 个答案:

答案 0 :(得分:0)

我看不出有什么,特别是你在这里做错了。如果你足够了解它,你可能会得到它。

但这不是正确的方法 - 至少,不是编写可维护的,可靠的WPF代码。您应该使用数据绑定来填充此控件。经过这么做的经验之后,你会发现它比你正在使用的代码-WPF-as-it-it-it-it-winForms方法更快,更容易开发。

以下是:

  1. 创建一个用于保存数据项的类,例如, Block。让它公开字符串Text和bool IsBanned属性。

  2. 创建ObservableCollection<Block>并使用从您的数据源创建的新Block对象填充它。

  3. 将集合暴露给绑定。有很多方法可以做到这一点;下面的示例假设您已使用Blocks键将其添加到窗口的资源字典中。您还可以在窗口中实现Blocks属性,或者(我在WPF中创建窗口或用户控件时的任何操作)创建一个公开Blocks属性并设置窗口的类DataContext到该类的实例。

  4. 现在把它放在窗口的XAML中:

      <ComboBox ItemsSource="{Binding {DynamicResource Blocks}}">
        <ComboBox.ItemTemplate>
          <DataTemplate>
            <Grid>
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
              </Grid.ColumnDefinitions>
              <TextBlock Grid.Column="0" Text="{Binding Text}">
                <TextBlock.Style>
                  <Style TargetType="TextBlock">
                    <Setter Property="Foreground" Value="Black"/>
                    <Style.Triggers>
                      <DataTrigger Binding="{Binding IsBanned}">
                        <Setter Property="Foreground" Value="Red"/>
                      </DataTrigger>
                    </Style.Triggers>
                  </Style>
                </TextBlock.Style>
              </TextBlock>
            </Grid>
          </DataTemplate>
        </ComboBox.ItemTemplate>
      </ComboBox>
    

    你实际上并不需要Grid(你也不需要设置Grid.Column,因为它默认为0);我只是把它放在那里,以便示例更准确地复制代码中的内容。另外,我没有在Tag上设置ComboBoxItem属性,但这是因为ComboBox的{​​{1}}包含该项的实际SelectedItem实例,这消除了对Block属性的需求。

    由于您使用的是Tag,因此您对该集合所做的任何更改(即添加/删除/重新排序其项目)都会自动反映在屏幕上的内容中;绑定会照顾你。

    如果在填充集合后项目的ObservableCollectionText属性发生变化,并且您需要IsBanned来反映这些变化,则需要实施{{ 1}}在ComboBox类中,让它在这些属性的setter中引发INotifyPropertyChanged