替换答:一个属性,视图模型与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

回到顶部