[英]WPF MainWindow toggle property in UserControl via ViewModel
[英]Binding Dependency Property of UserControl to MainWindow ViewModel in WPF
請允許我將問題簡化為基本問題。
我的項目中有一個UserControl1。 它具有如下所示的TextBox:
<TextBox Text="{Binding TextProperty}"/>
在后面的代碼中,我有一個像這樣的依賴項屬性:
public string TextProperty
{
get { return (string)GetValue(TextPropertyProperty); }
set { SetValue(TextPropertyProperty, value); }
}
public static readonly DependencyProperty TextPropertyProperty = DependencyProperty.Register("TextProperty", typeof(string), typeof(UserControl1), new PropertyMetadata(null));
而且UserControl的構造函數很簡單
public UserControl1()
{
InitializeComponent();
DataContext = this;
}
在MainWindow中,我有這個:
<userctrl:UserControl1 TextProperty="{Binding ABC, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Grid.Row="1" Text="{Binding PQR, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
現在,在MainWindow的viewModel中,我有:
private string _abc;
public string ABC
{
get { return _abc; }
set
{ _abc = "20";
OnPropertyChanged();
}
}
private string _pqr;
public string PQR
{
get { return _pqr; }
set
{
if(value != _pqr)
{
_pqr = value;
ABC = PQR;
OnPropertyChanged();
}
}
}
現在,即使UserControl也應該復制我在文本框中編寫的內容,對嗎?
但事實並非如此。 我已經在ABC的設置器上設置了斷點。 它得到更新,但該更新未到達UserControl。 我的直覺說綁定無提示地失敗了,這是因為我已經在UserControl的構造函數中將DataContext
設置this
。
我應該如何解決?
實際情況:
這是UserControl的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="5"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Command" Value="{Binding InputCommand}"/>
<Setter Property="CommandParameter" Value="{Binding Path=Content, RelativeSource={RelativeSource Self}}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderThickness" Value="5"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontFamily" Value="Times New Roman"/>
</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" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" IsEnabled="False" Background="Beige" Grid.Row="4" Text="{Binding PasswordDisplay, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</UserControl>
下面是代碼:
public partial class NodeGrid : UserControl
{
public NodeGrid()
{
InitializeComponent();
InputCommand = new InputCharacterCommand(this);
DataContext = this;
}
public string PasswordDisplay
{
get { return (string)GetValue(PasswordDisplayProperty); }
set { SetValue(PasswordDisplayProperty, value); }
}
public static readonly DependencyProperty PasswordDisplayProperty =
DependencyProperty.Register("PasswordDisplay", typeof(string), typeof(NodeGrid), new PropertyMetadata(""));
private ICommand _inputCommand;
public ICommand InputCommand
{
get
{
return _inputCommand;
}
set
{
_inputCommand = value;
}
}
public void AddCharacter(string input)
{
if (input != null)
{
PasswordDisplay = string.Concat(PasswordDisplay, input);
}
}
public bool InputAllowed()
{
if (PasswordDisplay == null)
{
return true;
}
if (PasswordDisplay.Length < 50)
{
return true;
}
return false;
}
private void OnPropertyChange([CallerMemberName] string property = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
}
class InputCharacterCommand : ICommand
{
private NodeGrid _vmodel;
public InputCharacterCommand(NodeGrid vm)
{
_vmodel = vm;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return (_vmodel.InputAllowed());
}
public void Execute(object parameter)
{
_vmodel.AddCharacter(parameter as string);
}
}
這是我在MainWindow中使用它的方式:
<StackPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<WrapPanel HorizontalAlignment="Center">
<Label Content="Enter PIN"/>
<TextBox CommandManager.PreviewCanExecute="HandleCanExecute" Foreground="Transparent" MinWidth="100" Padding="10,0" Text="{Binding PIN, UpdateSourceTrigger=PropertyChanged}"/>
</WrapPanel>
<customlock:NodeGrid MinHeight="250" MinWidth="500" PasswordDisplay="{Binding NodeGridDisplay}"/>
<Button VerticalAlignment="Center" HorizontalAlignment="Center" Content="Unlock!"/>
</StackPanel>
背后的代碼:
private void HandleCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
if (e.Command == ApplicationCommands.Cut ||
e.Command == ApplicationCommands.Copy ||
e.Command == ApplicationCommands.Paste)
{
e.CanExecute = false;
e.Handled = true;
}
}
現在,ViewModel:
private string _PIN;
public string PIN
{
get
{
return _PIN;
}
set
{
if(value != _PIN)
{
_PIN = value;
OnPropertyChanged();
NodeGridDisplay = HashIt(_PIN);
}
}
}
private string _nodeGridDisplay;
public string NodeGridDisplay
{
get
{
return _nodeGridDisplay;
}
set
{
if (value != _nodeGridDisplay)
{
_nodeGridDisplay = value;
OnPropertyChanged();
}
}
}
private string HashIt(string input)
{
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
return System.Text.Encoding.Default.GetString(md5.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input))).GetHashCode().ToString();
}
}
預期功能是什么?
讓我說明一下。
可以輸入PIN,其哈希將顯示在NodeGrid中。 然后,用戶將單擊將與哈希連接的字母。 然后,用戶可以單擊解鎖。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.