Добавление кнопок в WPF из ObservableCollection с использованием шаблона MVVM

Пытаюсь добавить кнопки в UserControl. Я должен следовать шаблону MVVM. Я создал класс DeviceButton с другим набором / получением и конструктором. В модели представления, используемой в качестве контекста данных, является ObservableCollection и метод получения для коллекции. Я привязал коллекцию к источнику ItemsControl и попытался добавить шаблон. Думаю, что-то не хватает, потому что кнопки не загружаются.

UserControl добавляется на вкладку (с помощью dragablz), которая также является частью ObservableCollection, также добавляется во время выполнения (это работает нормально). Идея состоит в том, что на вкладке есть список кнопок, которые должны быть созданы во время выполнения, где список извлекается из веб-службы, поэтому кнопки должны добавляться динамически / программно. Обзор - это всего лишь первая вкладка - шаблон для каждой вкладки (отражающий выбранные элементы) реализуется, когда кнопки работают. На данный момент я просто добавляю тестовую кнопку в коллекцию, но, как уже говорилось, она не отображается. Что мне не хватает?

У меня есть файл Overview.xaml:

<UserControl // attributes omitted to save spaces... ask if needed>

<StackPanel>
    <Border>
        <TextBlock FontSize="16" FontWeight="Bold" TextWrapping="WrapWithOverflow"
                   TextAlignment="Center" HorizontalAlignment="Center"
                   Foreground="{DynamicResource AccentColorBrush}">
            Welcome to Greenhouse App
        </TextBlock>
    </Border>

    <ItemsControl ItemsSource="{Binding DeviceButtons}">
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="{x:Type vmodel:DeviceButton}">
                <Button Width="50" Height="50" Margin="10 10 0 0" Command="{Binding OpenTab}"
                        CommandParameter="{Binding DeviceType}" HorizontalAlignment="Left"
                        VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}">
                    <StackPanel>
                        <Image Source="{Binding ImageUrl}" />
                    </StackPanel>
                </Button>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

    // Manually added test button...
    <Button x:Name="windMill" HorizontalAlignment="Left" Margin="10,0,0,0"
            VerticalAlignment="Top" Width="50" Height="50"
            Command="{Binding OpenTab}" FontFamily="Segoe Ui"
            Style="{DynamicResource SquareButtonStyle}">
        <StackPanel>
            <Image Source="/Greenhouse;component/Icons/Windmill.png" />
        </StackPanel>
    </Button
</StackPanel>

I'm trying to add an ObservableCollection of type DeviceButton, the _deviceButtons collection (Binded as ItemsSource to the ItemsControl)

Элементы tabList работают, просто находя, и я могу вручную добавить больше, если необходимо (позже они будут добавлены с помощью команды OpenNewTab, которая должна быть привязана к кнопкам)

Файл DeviceButton:

public class DeviceButton
{
    private readonly string _content;
    private readonly string _deviceType;
    private readonly string _imageUrl;

    public DeviceButton(string content, string deviceType, string imageUrl)
    {
        _content = content;
        _deviceType = deviceType;
        _imageUrl = imageUrl;
    }

    public string Content
    {
        get { return _content; }
    }

    public string DeviceType
    {
        get { return _deviceType; }
    }

    public string ImageUrl
    {
        get { return _imageUrl; }
    }
}

Коллекция находится в файле модели просмотра MainWindowViewModel.cs:

public class MainWindowViewModel : ViewModelBase, INotifyPropertyChanged
{
    public ICommand OpenTab { get; set; }

    private string tabControl { get; set; } = "0";
    private IInterTabClient _interTabClient;
    private ObservableCollection<TabContent> _tabContents = new ObservableCollection<TabContent>();
    private ObservableCollection<DeviceButton> _deviceButtons = new ObservableCollection<DeviceButton>();

    public MainWindowViewModel()
    {
        _interTabClient = new MyInterTabClient();

        DeviceButtons.Add(new DeviceButton("Windturbine", "windturbine", "/Greenhouse;component/Icons/Windmill.png"));

        TabContents.Add(new TabContent("Overview", new Overview()));

        OpenTab = new RelayCommand<object>(OpenNewTab);
    }

    private void OpenNewTab(object obj)
    {
        MessageBox.Show("Yo"); // Not yet implemented
        RaisePropertyChanged(() => tabControl);
    }

    public ObservableCollection<TabContent> TabContents
    {
        get { return _tabContents; }
    }

    public ObservableCollection<DeviceButton> DeviceButtons
    {
        get { return _deviceButtons; }
    }

    public IInterTabClient InterTabClient
    {
        get { return _interTabClient; }
    }
}

Кнопки не загружаются, когда я запускаю программу (только кнопка «тест», добавленная вручную в WPF).

UserControl, Обзор, считается вкладкой в ​​другом Controls.Metrowindow, MainWindow.xaml:

<Window.Resources>
    <Style TargetType="{x:Type dragablz:TabablzControl}">
        <Setter Property="CustomHeaderItemTemplate">
            <Setter.Value>
                <DataTemplate DataType="{x:Type viewmodel:TabContent}">
                    <TextBlock Text="{Binding Header}" />
                </DataTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate DataType="{x:Type viewmodel:TabContent}">
                    <ContentPresenter Margin="4" Content="{Binding Content}" />
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<dragablz:TabablzControl SelectedIndex="{Binding tabControl}" ItemsSource="{Binding TabContents}" x:Name="InitialTabablzControl" Margin="4 0 4 4">
    <dragablz:TabablzControl.InterTabController>
        <dragablz:InterTabController InterTabClient="{Binding MyInterTabClient}" />
    </dragablz:TabablzControl.InterTabController>
</dragablz:TabablzControl>

I guess it's an issue with the resources/binding in the Overview.xaml, but I've exhausted all suggested solutions I could find.


person eli    schedule 01.12.2015    source источник
comment
Я бы предложил использовать такой инструмент, как Snoop, чтобы убедиться, что ваш DataContext соответствует вашим ожиданиям ... Я подозреваю, что DataContext устанавливается на объект TabContent, у которого нет свойства DeviceButtons.   -  person Rachel    schedule 01.12.2015
comment
Вы пробовали ItemsSource = {Binding Path = DataContext.TabContents, RelativeSource = {RelativeSource AncestorLevel = 1, AncestorType = {x: Type Window}, Mode = FindAncestor}}? И да, вы должны использовать Snoop в таких случаях.   -  person galakt    schedule 02.12.2015
comment
@galakt Спасибо, что сделали. Если вы ответите, я помечу его как правильный.   -  person eli    schedule 03.12.2015
comment
@Rachel Спасибо, это действительно отличный инструмент, который я действительно искал.   -  person eli    schedule 03.12.2015
comment
@ user2832479 Конечно, ответ опубликован   -  person Rachel    schedule 03.12.2015


Ответы (2)


Проблема была в привязке

ItemsSource="{Binding Path=DataContext.TabContents, 
              RelativeSource={RelativeSource AncestorLevel=1, 
              AncestorType={x:Type Window}, Mode=FindAncestor}}"
person galakt    schedule 03.12.2015
comment
Небольшое замечание: я использовал DataContext.DeviceButtons вместо TabContents - person eli; 03.12.2015

Я подозреваю, что DataContext устанавливается на объект TabContent, у которого нет свойства DeviceButtons

Я бы посоветовал использовать такой инструмент, как Snoop, чтобы убедиться, что ваш DataContext соответствует вашим ожиданиям.

person Rachel    schedule 03.12.2015
comment
Я проголосовал за вас, но мои голоса не являются общедоступными, поскольку моя собственная репутация еще недостаточно высока. - person eli; 03.12.2015