C# 正确的MVVM实现动态生成的usercontrol
我的场景:我有一个usercontrol,由一个comboBox和一个TextBox组成。组合框应包含ObservableCollection中包含的数字 任务:ObservableCollection中的数字表示书籍章节的路径;因此,每一章都是独一无二的。意思:如果我有第1-5章,那么第一个userControl组合应该显示所有第1-5章(其中一个是随机选择的),第二个userControl组合包含所有章节,但不是前一个组合中选择的,依此类推。文本框用于章节的注释 到目前为止我所取得的成就:我目前没有模型;只有一个主视图模型(在我的例子中是ItemsViewModel)和一个用于我的userControl的视图模型(PathViewModel)。然后是主窗口视图 问题是:在我的主窗口上,我可以创建几个动态创建的用户控件。userControl文本框当前绑定到一个文本属性,而comboBox的索引绑定到另一个属性。但是我不知道: -如何访问特定用户控件的索引、选定项/值 -如何对组合框项/索引更改作出反应 这是我的密码: 用户控件C# 正确的MVVM实现动态生成的usercontrol,c#,wpf,mvvm,C#,Wpf,Mvvm,我的场景:我有一个usercontrol,由一个comboBox和一个TextBox组成。组合框应包含ObservableCollection中包含的数字 任务:ObservableCollection中的数字表示书籍章节的路径;因此,每一章都是独一无二的。意思:如果我有第1-5章,那么第一个userControl组合应该显示所有第1-5章(其中一个是随机选择的),第二个userControl组合包含所有章节,但不是前一个组合中选择的,依此类推。文本框用于章节的注释 到目前为止我所取得的成就:我
<UserControl> <StackPanel Orientation="Horizontal">
<ComboBox x:Name="combo" Margin="10" MinWidth="60" VerticalAlignment="Center" ItemsSource="{Binding AvailableNumbers}" SelectedIndex="{Binding TheIndex}" />
<TextBox Margin="10" MinWidth="120" Text="{Binding TheText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
最后是我的UserControl视图模型:
public class PathViewModel : NotifyPropertyChangedBase
{
public ObservableCollection<int> AvailableNumbers { get; set; } = new ObservableCollection<int>();
private int _theIndex;
public int TheIndex
{
get { return _theIndex; }
set
{
_theIndex = value;
OnPropertyChanged(ref _theIndex, value);
}
}
private int _theValue;
public int TheValue
{
get { return _theValue; }
set
{
_theValue = value;
OnPropertyChanged(ref _theValue, value);
}
}
private string _theText;
public string TheText
{
get { return _theText; }
set
{
_theText = value;
OnPropertyChanged(ref _theText, value);
}
}
public PathViewModel()
{
}
}
公共类PathViewModel:NotifyPropertyChangedBase
{
public ObservableCollection AvailableEnumbers{get;set;}=new ObservableCollection();
私人国际指数;
公共内部索引
{
获取{return\u theIndex;}
设置
{
_指数=数值;
已更改的房地产(参考指数、价值);
}
}
私人内部价值;
公共价值
{
获取{return\u theValue;}
设置
{
_价值=价值;
关于财产变更(参考价值,价值);
}
}
私有字符串_theText;
公共字符串文本
{
获取{return\u theText;}
设置
{
_文本=值;
已更改的属性(参考文本,值);
}
}
公共路径视图模型()
{
}
}
任何关于如何从这里开始的提示都会得到高度重视。因此关键是动态创建的每个
usercontrol
都应该创建一个ViewModel
。因此,如果在组合框中有事件
,它将在视图模型中触发。这一切都取决于您如何动态创建usercontrols
您必须在资源中创建如上所述的数据模板,您可以在一个集合中生成您的ViewModels,该集合将创建您的usercontrols
,然后您将拥有该集合中所有ViewModels的控件。可能您的PathViewModel
可以存储选定的值并对其执行操作。因此,当您选择章节PathViewModel
存储该决策时,您将创建一个存储该决策的章节。选择的索引将是复杂的,因为它必须考虑先前的选择。如何禁用已经选择的章节?Albin,所以我不能完全确定:数据模板在userControl.xaml上?如果是这样,代码隐藏的事件如何与我的viewModel交互?或者viewModel集合也是userControl viewModel的一部分?DataTemplate应位于父视图的resource或App.xaml或resource dictionary中。ViewModel集合应位于父ViewModel中。
public class ItemsViewModel : NotifyPropertyChangedBase
{private int _aNumber;
public int ANumber
{
get { return _aNumber; }
set { _aNumber = value;
OnPropertyChanged(ref _aNumber, value);
}
}
public ObservableCollection<PathViewModel> PathViewModels { get; set; } = new
ObservableCollection<PathViewModel>();
public ObservableCollection<int> AllNumbers { get; set; } = new ObservableCollection<int>();
public ItemsViewModel()
{
UCCreationCommand = new CommandDelegateBase(UCCreationExecute, UCCreationCanExecute);
UCDeletionCommand = new CommandDelegateBase(UCDeletionExecute, UCDeletionCanExecute);
ReadoutCommand = new CommandDelegateBase(ReadoutExecute, ReadoutCanExecute);
AllNumbers.Add(1);
AllNumbers.Add(2);
AllNumbers.Add(3);
AllNumbers.Add(4);
AllNumbers.Add(5);
}
private bool ReadoutCanExecute(object paramerter)
{
if (PathViewModels.Count > 0)
{
return true;
}
return false;
}
private void ReadoutExecute(object parameter)
{
//just for testing
}
public ICommand UCCreationCommand { get; set; }
public ICommand UCDeletionCommand { get; set; }
public ICommand ReadoutCommand { get; set; }
private bool UCCreationCanExecute(object paramerter)
{
if (PathViewModels.Count < 8)
{
return true;
}
else
{
return false;
}
}
private void UCCreationExecute(object parameter)
{
PathViewModel p = new PathViewModel();
foreach (int i in AllNumbers)
{
p.AvailableNumbers.Add(i);
}
int rndIndex = 0;
Random rnd = new Random();
//creates a random chapter index
rndIndex = rnd.Next(0, p.AvailableNumbers.Count);
//just explicit for debugging reasons
p.TheIndex = rndIndex;
PathViewModels.Add(p);
}
private bool UCDeletionCanExecute(object paramerter)
{
if (PathViewModels.Count != 0)
{
return true;
}
else
{
return false;
}
}
private void UCDeletionExecute(object parameter)
{
PathViewModel p = new PathViewModel();
int delIndex = PathViewModels.Count - 1;
p = PathViewModels[delIndex];
AllNumbers.Add((int)p.TheValue+1);
PathViewModels.Remove(p);
}
}
public class PathViewModel : NotifyPropertyChangedBase
{
public ObservableCollection<int> AvailableNumbers { get; set; } = new ObservableCollection<int>();
private int _theIndex;
public int TheIndex
{
get { return _theIndex; }
set
{
_theIndex = value;
OnPropertyChanged(ref _theIndex, value);
}
}
private int _theValue;
public int TheValue
{
get { return _theValue; }
set
{
_theValue = value;
OnPropertyChanged(ref _theValue, value);
}
}
private string _theText;
public string TheText
{
get { return _theText; }
set
{
_theText = value;
OnPropertyChanged(ref _theText, value);
}
}
public PathViewModel()
{
}
}