替换答:一个属性,视图模型与B中的每个文本框:一个属性返回(可观察)收集
让我们这两个枚举和模型类:替换答:一个属性,视图模型与B中的每个文本框:一个属性返回(可观察)收集
public enum A {
A1,
A2,
A3,
A4
}
public enum B
{
B1,
B2,
B3
}
// model class
public class MyModel
{
private float[][] array;
public MyModel()
{
array = new float[Enum.GetNames(typeof(A)).Length][];
foreach (A a in EnumUtil.GetValues<A>())
{
array[(int) a] = new float[Enum.GetNames(typeof(B)).Length];
}
}
public A EnumerationA { get; set; }
public B EnumerationB { get; set; }
public float this[A a, B b]
{
get
{
return array[(int) a][(int) b];
}
set
{
array[(int)a][(int)b] = value;
}
}
public float[] ArraySlice
{
get
{
return array[(int) EnumerationA];
}
}
}
比方说,我们想实现一个包含一组用于枚举A的RadioButton的视图,对于每个枚举B我们都希望一个TextBox。
更改单选按钮组中的单选按钮将允许在文本框中编辑不同的值集,改回将显示先前输入的值。
最简单的方法,我能想到的,做到这一点是:
public class MyViewModel : ViewModelBase {
private MyModel _myModel;
public A EnumerationA
{
get
{
return _myModel.EnumerationA;
}
set
{
if (Enum.Equals(_myModel.EnumerationA, value) == false)
{
_myModel.EnumerationA = value;
RaisePropertyChanged("EnumerationA");
}
}
}
public float ValueB1
{
get
{
return _myModel[EnumerationA, B.B1];
}
set
{
if (_myModel[EnumerationA, B.B1] != value)
{
_myModel[EnumerationA, B.B1] = value;
RaisePropertyChanged("ValueB1");
}
}
}
// Analogously for ValueB2 and ValueB3 properties
}
和视图:
<Grid> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Enum A" />
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Vertical">
<RadioButton IsChecked="{Binding Path=EnumerationA, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:A.A1}}" Content="A1" />
<RadioButton IsChecked="{Binding Path=EnumerationA, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:A.A2}}" Content="A2" />
<RadioButton IsChecked="{Binding Path=EnumerationA, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:A.A3}}" Content="A3" />
<RadioButton IsChecked="{Binding Path=EnumerationA, Converter={StaticResource EnumToBoolConverter}, ConverterParameter={x:Static model:A.A4}}" Content="A4 />
</StackPanel>
<Label Grid.Row="1" Grid.Column="0" Content="Float Values" />
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Vertical">
<StackPanel Orientation="Horizontal"><Label Content="B1" /><TextBox Text="{Binding Path=ValueB1}" /></StackPanel>
<StackPanel Orientation="Horizontal"><Label Content="B2" /><TextBox Text="{Binding Path=ValueB2}" /></StackPanel>
<StackPanel Orientation="Horizontal"><Label Content="B3" /><TextBox Text="{Binding Path=ValueB3}" /></StackPanel>
</StackPanel>
</Grid>
也就是说,这种方法创建一个属性对于每个TextBox并在单选按钮组选择更改时执行PropertyNotification。
问:
是否有可能以这样一种方式,视图模型只公开一个属性,而不是三个属性(ValueB1,ValueB2,ValueB3)做到这一点: 这个单一属性将返回一个ObservableCollection < >或IList(或类似的索引选择)?
我想到了一种可能的方式,这可能来完成: 在VM我们将不得不像
public ObservableCollection<float> ArraySlice {
get
{
return new ObservableCollection<float>(_myModel.ArraySlice);
}
}
在查看
<StackPanel Orientation="Horizontal"> <Label Content="B1" />
<TextBox Text="{Binding Path=WindSpeedAverage, Converter={StaticResource EnumToObservableCollectionConverter}, ConverterParameter={x:Static model:B.B1}}" />
</StackPanel>
这EnumToObservableCollectionConverter - 一个这种方式很容易,它会把价值作为IList和简单的方式来施展虽然我实现了ConvertBack方法,但我只是简单地更新ObservableCollection而不更新模型类中的值本身。
这怎么办?有没有这种我缺少的共同模式
回答:
首先,我的道歉:我离开办公室前的最后一分钟回答。
所以,这里是我如何处理您的问题,但还有很多其他解决方案。按照你的意愿创建一个图形用户界面是最简单但最简单的方式(据我所知,正确)。
让我们从视图模型开始:您的案例看起来是一个简单的主 - 细节上下文,但它也可以被看作是一个分层上下文。
public class VM {
public VM()
{
this._aItems = new ObservableCollection<VMA>();
}
private ObservableCollection<VMA> _aItems;
public Collection<VMA> AItems
{
get { return this._aItems; }
}
}
public class VMA
{
public VMA()
{
this._bItems = new ObservableCollection<VMB>();
}
public string Title { get; set; }
private ObservableCollection<VMB> _bItems;
public Collection<VMB> BItems
{
get { return this._bItems; }
}
}
public class VMB : INotifyPropertyChanged
{
public string Title { get; set; }
private string _value;
public string Value
{
get { return this._value; }
set
{
if (this._value != value)
{
this._value = value;
this.OnPropertyChanged("Value");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(
this,
new PropertyChangedEventArgs(name)
);
}
}
}
请注意,“值”属性的类型是“字符串”,尽管目标值应限制为浮点型。这是因为一个字符串总是被接受,你可以实现你自己的验证逻辑。相反,数字属性可能会导致异常,而输入的字符不允许作为数字。
以上的ViewModels在下列方式填充(如例如):
public partial class MainWindow : Window {
public MainWindow()
{
InitializeComponent();
var rnd = new Random();
var vm = new VM();
this.DataContext = vm;
//enum "A"
foreach (var a in Enum.GetNames(typeof(A)))
{
var vma = new VMA();
vma.Title = a;
vm.AItems.Add(vma);
//enum "B"
foreach (var b in Enum.GetNames(typeof(B)))
{
var vmb = new VMB();
vmb.Title = b;
vmb.Value = rnd.Next(1000).ToString();
vma.BItems.Add(vmb);
}
}
}
}
请注意,我没有使用型号为简单起见,但你可以随时添加。相反,我选择填充随机整数。
最后,这里是XAML:
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350" Width="525"
>
<Window.Resources>
<DataTemplate x:Key="tplA">
<RadioButton
Content="{Binding Path=Title}"
IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBoxItem}}"
/>
</DataTemplate>
<DataTemplate x:Key="tplB">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Title}" Width="30" />
<TextBox Text="{Binding Path=Value}" Width="100" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ListBox
ItemsSource="{Binding Path=AItems}"
ItemTemplate="{StaticResource tplA}"
Width="150"
Height="200"
Grid.Column="0"
x:Name="L1"
>
</ListBox>
<ListBox
ItemsSource="{Binding Path=SelectedItem.BItems, ElementName=L1}"
ItemTemplate="{StaticResource tplB}"
Width="150"
Height="200"
Grid.Column="1"
>
</ListBox>
</Grid>
</Window>
的视觉效果看起来像下面的图片。
以上是 替换答:一个属性,视图模型与B中的每个文本框:一个属性返回(可观察)收集 的全部内容, 来源链接: utcz.com/qa/259420.html