Dobrze, najlepiej utwórz sobie nowy projekt, ponieważ napisałem coś takiego:
Najpierw XAML
Kopiuj
<Window x:Class="_4programmersWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:_4programmersWPF"
xmlns:vm="clr-namespace:_4programmersWPF"
mc:Ignorable="d"
Name="Window" WindowStartupLocation="CenterScreen"
SizeToContent="Height" Width="230.674">
<Window.DataContext>
<vm:MainWindowVM/>
</Window.DataContext>
<StackPanel>
<Label Margin="2" FontSize="18" Padding="2"
Content="Categories:"/>
<TextBox Margin="2" FontSize="18" Padding="2"
Text="{Binding CategoryName,UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Key="Return" Command="{Binding AddCategory}"/>
</TextBox.InputBindings>
</TextBox>
<Button Margin="2" FontSize="18" Padding="2"
Content="Add Category"
Command="{Binding AddCategory}"/>
<ComboBox FontSize="18" Padding="2" Margin="2"
DisplayMemberPath="Name"
ItemsSource="{Binding Categories,UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SelectedCategory,UpdateSourceTrigger=PropertyChanged}"/>
<Label Margin="2" FontSize="18" Padding="2"
Content="Channels:"/>
<TextBox Margin="2" FontSize="18" Padding="2"
Text="{Binding ChannelName,UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Key="Return" Command="{Binding AddChannel}"/>
</TextBox.InputBindings>
</TextBox>
<Button Margin="2" FontSize="18" Padding="2"
Content="Add Channel"
Command="{Binding AddChannel}"/>
<ComboBox FontSize="18" Padding="2" Margin="2"
ItemsSource="{Binding SelectedCategory.Channels,UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SelectedCategory.SelectedChannel,UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</Window>
Teraz viewmodel wybranej kategorii
Kopiuj
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _4programmersWPF
{
public class CategoryVM : ViewModelBase
{
public string Name { get; set; }
private IList<string> channels;
public IList<string> Channels
{
get { return this.channels; }
set
{
this.channels = value;
this.OnPropertyChanged(nameof(this.Channels));
}
}
private string selectecChannel;
public string SelectedChannel
{
get { return this.selectecChannel; }
set
{
this.selectecChannel = value;
this.OnPropertyChanged(nameof(this.SelectedChannel));
}
}
public CategoryVM()
{
this.Channels = new ObservableCollection<string>();
}
}
}
Viewmodel okna głownego
Kopiuj
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace _4programmersWPF
{
public class MainWindowVM : ViewModelBase
{
private string categoryName;
public string CategoryName
{
get { return this.categoryName; }
set
{
this.categoryName = value;
this.OnPropertyChanged(nameof(this.CategoryName));
}
}
private string channelName;
public string ChannelName
{
get { return this.channelName; }
set
{
this.channelName = value;
this.OnPropertyChanged(nameof(this.ChannelName));
}
}
private IList<CategoryVM> categories;
public IList<CategoryVM> Categories
{
get { return this.categories; }
set
{
this.categories = value;
this.OnPropertyChanged(nameof(this.Categories));
}
}
private CategoryVM selectedCategory;
public CategoryVM SelectedCategory
{
get { return this.selectedCategory; }
set
{
this.selectedCategory = value;
this.OnPropertyChanged(nameof(this.SelectedCategory));
if (this.SelectedCategory != null)
{
this.SelectedCategory.SelectedChannel = null;
}
}
}
public MainWindowVM()
{
this.Categories = new ObservableCollection<CategoryVM>();
}
public ICommand AddCategory
{
get
{
return new RelayCommand(() =>
{
this.Categories.Add(new CategoryVM { Name = this.CategoryName });
this.SelectedCategory = this.Categories.SingleOrDefault(c => c.Name == this.CategoryName);
this.SelectedCategory.SelectedChannel = null;
this.CategoryName = "";
},
() => !string.IsNullOrWhiteSpace(this.CategoryName));
}
}
public ICommand AddChannel
{
get
{
return new RelayCommand(() =>
{
this.SelectedCategory.Channels.Add(this.ChannelName);
this.SelectedCategory.SelectedChannel = this.SelectedCategory.Channels.SingleOrDefault(c => c == this.ChannelName);
this.ChannelName = "";
},
() => !string.IsNullOrWhiteSpace(this.ChannelName) && this.SelectedCategory != null);
}
}
}
}
I standardowa klasa ViewModelBase
Kopiuj
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
namespace _4programmersWPF
{
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string property)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}
Działa jak chciałeś. Poskładaj, skompiluj, a się przekonasz ;)