Я пытаюсь добавить кнопки в UserControl. Я должен следовать шаблону MVVM. Я создал класс DeviceButton с разными установками/get и конструктором. В viewmodel, используемом как datacontext, является ObservableCollection и get-method для коллекции. Я связал сборку с источником ItemsControl и попытался добавить шаблон. Наверное, я что-то упустил, потому что кнопки не будут загружаться.Добавление кнопок в WPF из ObservableCollection с использованием шаблона MVVM
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>
Я пытаюсь добавить ObservableCollection типа DeviceButton, коллекция _deviceButtons (переплетено, как ItemsSource к 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; }
}
}
Коллекция находится в файле ViewModel, 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>
Я предполагаю, что это проблема с ресурсами/связывание в Overview.xaml, но я исчерпал все предлагаемые решения, которые я мог найти.
Я предложил бы использовать такой инструмент, как [Snoop] (https://snoopwpf.codeplex.com/), чтобы проверить ваш DataContext является то, что вы ожидаете ... Я подозреваю, 'DataContext' устанавливается в объект' TabContent', который не имеет свойства 'DeviceButtons'. – Rachel
Вы пробовали ItemsSource = "{Binding Path = DataContext.TabContents, RelativeSource = {RelativeSource AncestorLevel = 1, AncestorType = {x: Type Window}, Mode = FindAncestor}}"? И да, вы должны использовать Snoop в таких случаях. – galakt
@galakt Спасибо, что сделал. Если вы сделаете ответ, я буду отмечать его как правильный ответ. – eli