ViewModel для пользовательского элемента управления?
У меня есть приложение WPF, в котором я пытаюсь создать экранную клавиатуру в качестве пользовательского элемента управления.
Вот XAML для дизайна:
<UserControl x:Class="MyDiskTools.UserControls.NodeGrid.NodeGrid" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:MyDiskTools.UserControls.NodeGrid" mc:Ignorable="d"> <Grid> <Grid.Resources> <Style TargetType="Button"> <Setter Property="Padding" Value="{Binding ButtonPadding, FallbackValue=5}"/> <Setter Property="BorderThickness" Value="{Binding ButtonBorderThickness, FallbackValue=1}"/> <Setter Property="Command" Value="{Binding InputCharacterCommand}"/> <Setter Property="CommandParameter" Value="{Binding Path=Content, RelativeSource={RelativeSource Self}}"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="BorderThickness" Value="{Binding HighlightBorderThickness, FallbackValue=5}"/> <Setter Property="FontSize" Value="{Binding HighlightFontSize, FallbackValue=20}"/> </Trigger> </Style.Triggers> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <UniformGrid Grid.Row="0" Rows="1"> <Button Content="A" /> <Button Content="B" /> <Button Content="C" /> <Button Content="D" /> <Button Content="E" /> <Button Content="F" /> </UniformGrid> <UniformGrid Grid.Row="1" Rows="1"> <Button Content="G" /> <Button Content="H" /> <Button Content="I" /> <Button Content="J" /> <Button Content="K" /> <Button Content="L" /> <Button Content="M" /> </UniformGrid> <UniformGrid Grid.Row="2" Rows="1"> <Button Content="N" /> <Button Content="O" /> <Button Content="P" /> <Button Content="Q" /> <Button Content="R" /> <Button Content="S" /> <Button Content="T" /> </UniformGrid> <UniformGrid Grid.Row="3" Rows="1"> <Button Content="U" /> <Button Content="V" /> <Button Content="W" /> <Button Content="X" /> <Button Content="Y" /> <Button Content="Z" /> </UniformGrid> <TextBox Name="InputMessage" IsEnabled="False" Background="Beige" Grid.Row="4" Text="{Binding PasswordDisplay, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> </Grid> </UserControl>
Код-за-Здесь:
public partial class NodeGrid : UserControl { public NodeGrid() { InitializeComponent(); DataContext = new NodeGridVM(); } public string Message { get { return InputMessage.Text; } } #region Dependency Properties [TypeConverter(typeof(LengthConverter))] public double InternalPadding { get { return (double)GetValue(InternalPaddingProperty); } set { SetValue(InternalPaddingProperty, value); } } // Using a DependencyProperty as the backing store for InternalPadding. This enables animation, styling, binding, etc... public static readonly DependencyProperty InternalPaddingProperty = DependencyProperty.Register("InternalPadding", typeof(double), typeof(NodeGrid), new PropertyMetadata(double.NaN)); public double ButtonHeight { get { return (double)GetValue(ButtonHeightProperty); } set { SetValue(ButtonHeightProperty, value); } } // Using a DependencyProperty as the backing store for ButtonHeight. This enables animation, styling, binding, etc... public static readonly DependencyProperty ButtonHeightProperty = DependencyProperty.Register("ButtonHeight", typeof(double), typeof(NodeGrid), new PropertyMetadata(double.NaN)); #endregion }
... а ViewModel-это:
class NodeGridVM : INotifyPropertyChanged { private string _passwordDisplay = ""; public string PasswordDisplay { get { return _passwordDisplay; } set { if (value != _passwordDisplay) { _passwordDisplay = value; OnPropertyChange(); } } } private ICommand _inputCharacterCommand; public ICommand InputCharacterCommand { get { if (_inputCharacterCommand == null) { InputCharacterCommand = new InputCharacterCommand(this); } return _inputCharacterCommand; } set { _inputCharacterCommand = value; } } public void AddCharacter(string input) { if (input != null) { PasswordDisplay = String.Concat(PasswordDisplay, input); } } private void OnPropertyChange([CallerMemberName] string property = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); } public event PropertyChangedEventHandler PropertyChanged; public bool InputAllowed() { if (PasswordDisplay == null) { return true; } if (PasswordDisplay.Length > 20) { return false; } return true; } } class InputCharacterCommand : ICommand { private NodeGridVM _viewmodel; public InputCharacterCommand(NodeGridVM vm) { _viewmodel = vm; } public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) { return (_viewmodel.InputAllowed()); } public void Execute(object parameter) { _viewmodel.AddCharacter(parameter as String); } }
Пожалуйста, обратите внимание, что это всего лишь набросок кода, и для дальнейшего использования будут созданы дополнительные свойства зависимостей.
Что я уже пробовал:
Однако, согласно большинству мнений в интернете, предоставление Usercontrol собственной модели представления-крайне плохая идея. Должен ли я тогда отказаться от ViewModel и просто поместить всю логику в файл code-behind?
[no name]
"согласно большинству мнений в интернете, предоставление Usercontrol собственной модели представления-это крайне плохая идея".... согласно каким источникам?
Sabyasachi Mukherjee
Источник 1:
http://stackoverflow.com/questions/1939345/wpf-should-a-user-control-have-its-own-viewmodel
[no name]
Итак, один человек говорит, что это плохая идея, и вы интерпретируете это как Евангелие? Я не думаю, что это плохая идея. Это зависит от приложения.
Sabyasachi Mukherjee
Вообще говоря, это хорошая практика, чтобы дать Usercontrol свою собственную виртуальную машину? Или это всецело зависит от конкретных случаев?
[no name]
Опять же, это зависит.
Sabyasachi Mukherjee
Источник 2:
http://stackoverflow.com/questions/28175338/hair-loss-and-mvvm-user-controls
Ludovic Feltz
Это зависит от того, что вы действительно хотите сделать... Источник 1 был обновлен с ответом, который объясняет, почему вы можете...