【问题标题】:Confusion about WPF binding关于 WPF 绑定的困惑
【发布时间】:2010-05-21 01:40:22
【问题描述】:

我正在尝试将堆栈面板中排列的 2D 按钮数组绑定到 2D ObservableCollection...

但是,恐怕我对绑定的一些基本知识还不太了解。

我的 XAML:

    <Window.Resources>
    <DataTemplate x:Key="ItemsAsButtons">
        <Button Content="{Binding}" Height="100" Width="100"/>
    </DataTemplate>
    <DataTemplate x:Key="PanelOfPanels">
        <ItemsControl ItemsSource="{Binding Path=DayNumbers}" ItemTemplate="   {DynamicResource ItemsAsButtons}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </DataTemplate>
    </Window.Resources>

...
        <ItemsControl x:Name="DaysPanel" Grid.ColumnSpan="7" Grid.Row="2"
                      ItemTemplate="{DynamicResource PanelOfPanels}"/>

我的 C# 代码: 后端:

/// <summary>
/// Window BE for Calendar.xaml
/// </summary>
public partial class Calendar : Window
{

    private CalendarViewModel _vm;
    public Calendar()
    {
        InitializeComponent();
        _vm = new CalendarViewModel();
        this.DataContext = _vm; 
    }
}

视图模型:

class CalendarViewModel
{
    CalendarMonth _displayedMonth;
    EventCalendar _calendar;

    public CalendarViewModel()
    {
        _displayedMonth = new CalendarMonth();
    }

    public ObservableCollection<ObservableCollection<int>> DayNumbers
    {
        get
        {
            return _displayedMonth.DayNumbers;
        }
    }
}

我正在尝试使用 CalendarViewModel.DayNumbers 中的值填充按钮 - 但按钮没有出现。我的绑定显然有问题。

【问题讨论】:

    标签: c# wpf xaml mvvm binding


    【解决方案1】:

    将您所有的DynamicResource 更改为StaticResource。这不应该停止它的工作,但在运行时可能效率低下。查看this page 了解 WPF 资源概述。

    您的ItemsControl 也未绑定到DayNumbers。像这样添加绑定:

    <ItemsControl x:Name="DaysPanel" Grid.ColumnSpan="7" Grid.Row="2"
                      ItemTemplate="{StaticResource PanelOfPanels}"
                      ItemsSource={Binding DayNumbers}/>
    

    当您在日历窗口上设置DataContext 时,您可以设置哪个对象将成为整个窗口的默认绑定源。您没有指定 ViewModel 的哪个属性绑定到 ItemsControl。这就是上面的代码所做的。

    编辑 因为您要覆盖ItemsControl 的项目模板并在那里提供一个集合容器,所以您还需要为其提供ItemsSource。语法{Binding} 仅表示绑定到每个成员或枚举,在本例中为ObservableCollection&lt;int&gt;

    重申一下,模板就是这样 - 用于显示数据的模板。它应该是可重用的,您应该能够将它绑定到您想要的任何模型。经验法则 - 与实际数据的数据绑定应该发生在控件上,而不是模板上。

    【讨论】:

    • 模板中的代码不提供绑定吗? 我尝试将您推荐的代码行添加到 ItemsControl 的实际调用中,但这没有帮助。
    • 我错过了那一点。没试过这样,感觉很别扭。模板应该定义控件的外观,而不是绑定到数据。
    • 模板中的行原来是强制性的,但必须更改为 ItemsSource="{Binding}"。你是说模板不应该提供绑定 - 有没有办法解决这个问题(其他然后在 C# 代码中手动绑定)
    【解决方案2】:
      1234563 >
    1. 一旦你这样做,它将为DayNumbers 中的每个项目应用&lt;DataTemplate x:Key="PanelOfPanels"&gt;。注意DataTemplate 中的DataTemplateDataContextDayNumbers 中的每个元素,它的类型是ObservableCollection&lt;int&gt;。在这里您不能指定ItemsSource="{Binding Path=DayNumbers}",因为DayNumbers 不是ObservableCollection&lt;int&gt; 中的有效属性。相反,由于ObservableCollection&lt;int&gt; 已经是IEnumerable,所以不指定ItemsSource 应该没问题,因为它默认绑定到DataContext

    2. 最后,它进入你最内心的&lt;DataTemplate x:Key="ItemsAsButtons"&gt;,你可以像以前一样把按钮放在那里。

    希望它能澄清一点。对不起,我没有环境来测试它并给你解决方案。

    调试 WPF 绑定并不简单。一个提示是您可以使用虚拟转换器并在 Convert 方法中设置断点以查看它绑定的内容。

    public class DebugConverter1 : IValueConverter
      {
        #region IValueConverter Members
    
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
           return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
          return value;
        }
    
        #endregion
      }
    
    {Binding Converter={StaticResource debugConverter1}}
    

    【讨论】:

    • 现在我明白了——我需要在上层列表中指定一个普通绑定,我现在可以看到 Igor 在说什么了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-05
    • 2012-03-06
    • 2013-02-21
    • 1970-01-01
    • 2014-06-06
    • 2021-01-29
    • 2019-05-17
    相关资源
    最近更新 更多