【问题标题】:WPF ItemsSource works in code-behind but not in XAMLWPF ItemsSource 在代码隐藏中有效,但在 XAML 中无效
【发布时间】:2011-06-09 11:46:34
【问题描述】:

我有一个简单的组合框,里面有一个复选框:

<ComboBox Height="23" HorizontalAlignment="Left" Margin="158,180,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" ItemsSource="{Binding collection}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <CheckBox Content="{Binding Name}"></CheckBox>
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>

datacontext 只是后面的代码,为了测试它,我使用以下代码:

public ObservableCollection<Foo> collection { get; set; }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        collection = new ObservableCollection<Foo>();
        this.comboBox1.ItemsSource = collection;
        Foo f = new Foo("DSD");
        collection.Add(f);
    }

当我在代码中设置 ItemsSource 时,它​​工作正常,但我想在 Xaml 中设置 ItemsSource,但是使用上面的 Xaml 不起作用。我也尝试将其设置为 Path = ""。有人知道为什么吗?

谢谢

【问题讨论】:

    标签: c# wpf itemssource


    【解决方案1】:

    您需要将 DataContext 分配给控件。类似:

    var window = new Window1();
    window.DataContext = new WindowDC();
    window.Show();
    

    其中Window1 类包含组合框,WindowDC 是这样的:

    public class WindowDC
    { 
       public ObservableCollection<Foo> collection { get; set; }
    }
    

    这就是它的工作原理。

    您实际上所做的是将collection 放入控件类,并将数据上下文设置为仅用于组合框。

    但是,出于测试目的,您仍然可以在控件构造函数中设置 Combox.Datacontext。

    【讨论】:

      【解决方案2】:

      WPF 中的绑定总是有一个 Source。如果您没有在绑定本身中指定源,那么它将隐式使用控件的 DataContext 或其祖先。因此,如果要绑定到代码隐藏文件中的属性,则必须将 DataContext 设置为包含 collection 属性的类的对象。在您的情况下,这是 Window (this) 的实例。

      DataContext = this;

      正如评论者所指出的,将业务逻辑或数据放在代码隐藏文件中并不是一种好的风格。所以考虑编写一个单独的类,其中包含您的collection 属性,您可以使用它来初始化您的DataContext。如果你正在编写更大的应用程序,你应该看看像 MVVM 这样的模式,它使用数据绑定来更好地分离视图和模型。

      编辑:更改顺序和合并反馈

      【讨论】:

      • 不要那样做。这是错误的,它打破了 DataContext 的整个想法,它用于将业务逻辑与 perpersentation 分开。不,不。
      • 我认为对此投反对票是不公平的。该问题没有任何关联的上下文。他只想知道为什么他的样本不起作用,我给了他缺少的链接。我们在这里讨论的不是概念证明的架构。举个例子,不用解释如何使用MVVM之类的。请考虑收回此反对票。
      • 无论如何我都采纳了您的反馈并在原始答案中添加了评论。
      【解决方案3】:

      确保您的代码中存在公共属性collection。

      在后面的代码中也做this.DataContext = this

      最后实现INotifyPropertyChanged 告诉视图一旦你在其中添加项目你已经改变了集合

      public ObservableCollection<Foo> Collection 
      { 
      get
          {
          return collection;
          }
       set
          {
          collection = value;
          OnPropertyChanged("Collection");
      
          }
      
          private void button1_Click(object sender, RoutedEventArgs e)
          {
              collection = new ObservableCollection<Foo>();
              //this.comboBox1.ItemsSource = collection;
              Foo f = new Foo("DSD");
              collection.Add(f);
              OnPropertyChanged("Collection");
          }
      

      【讨论】:

      • INotifyPropertyChanged 不是必需的。 button_click() 中的数据上下文未更改
      【解决方案4】:

      当您在后面的代码中设置组合的项目源时它正在工作,因为组合的源正在更新,就像在 XAML 中设置项目源一样,您必须使用 INotifyPropertyChanged 创建一个属性,每次您都保持更新组合的项目源通过此属性更新您的收藏..

       private ObservableCollection<Foo> _Collection;
       public ObservableCollection<Foo> Collection 
      { 
      get
      {
      return collection;
      }
       set
      {
      collection = value;
      OnPropertyChanged("Collection");
      }
      

      现在,当您在单击按钮时填充集合时,您只需将该集合在属性中设置为..

       _Collection = new ObservableCollection<Foo>();
       Foo f = new Foo("DSD");
       _Collection .Add(f);
        Collection = _Collection ; //here property call OnPropertyChange 
      

      同样,您可以向任何控件提供数据。它只是 INotifyPropertyChanged 属性的游戏。 希望对你有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-09
        • 1970-01-01
        • 2011-04-21
        • 1970-01-01
        • 2019-05-18
        • 2013-01-16
        • 2011-12-17
        • 2019-04-28
        相关资源
        最近更新 更多