Путаница с привязкой WPF - PullRequest
0 голосов
/ 21 мая 2010

Я пытаюсь привязать 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; 
    }
}

ViewModel:

class CalendarViewModel
{
    CalendarMonth _displayedMonth;
    EventCalendar _calendar;

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

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

Я пытаюсь заполнить кнопки значениями из CalendarViewModel.DayNumbers - кнопки не отображаются. Я явно делаю что-то не так с моим связыванием.

Ответы [ 2 ]

3 голосов
/ 21 мая 2010

Измените все свои DynamicResource на StaticResource. Это не должно останавливать его работу, но может быть неэффективным во время выполнения. Посмотрите эту страницу для обзора ресурсов 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<int>.

Просто повторюсь, шаблон именно такой - шаблон для отображения данных. Он должен быть многоразовым, вы должны иметь возможность привязать его к любой модели, которую вы хотите. Практическое правило: привязка данных к фактическим данным должна происходить в элементе управления, а не в шаблоне.

2 голосов
/ 21 мая 2010
  1. Как сказал Игорь, вам нужно указать ItemsSource={Binding DayNumbers} в самом внешнем ItemsControl, в противном случае он связывается с DataContext, то есть CalendarViewModel, а не IEnumerable.

  2. Как только вы это сделаете, он будет применяться <DataTemplate x:Key="PanelOfPanels"> для каждого элемента внутри DayNumbers. Обратите внимание, что DataContext из DataTemplate в каждом элементе в DayNumbers, который имеет тип ObservableCollection<int>. Здесь вы не можете указать ItemsSource="{Binding Path=DayNumbers}", так как DayNumbers не является допустимым свойством в ObservableCollection<int>. Вместо этого, поскольку ObservableCollection<int> уже является IEnumerable, не следует указывать ItemsSource, поскольку по умолчанию он будет привязан к DataContext.

  3. Наконец, он переходит к вашему внутреннему <DataTemplate x:Key="ItemsAsButtons">, и вы можете поместить туда кнопку, как и вы.

Надеюсь, это прояснится немного. Извините, у меня нет среды, чтобы проверить это и дать вам решение.

Отладка привязок 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}}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...