允许我将问题简化为基本块。
我的项目中有一个usercontrol1。它具有这样的文本框:
<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的Setter设置了断点。它已更新,但该更新未能达到USERCONTROL。我的直觉说绑定正在默默失败,这是因为我将 DataContext
设置为usercontrol构造函数中的 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();
}
}
什么是预期功能?
让我说明它。
锁
一个人可以输入引脚,其哈希将显示在节点格里德中。然后,用户将单击将与哈希串联的字母。然后用户可以单击解锁。
您应该在 UserControl
中使用 ElementName
或使用raltiveresource查找它,并且不应使用dataContext = this。(请参阅此答案和此链接)
给您的USERCONTROL一个名称并写下:
<UserControl x:Class= ......
Name="userControl">
<TextBox Text="{Binding Text, ElementName = userControl}"/>
</UserControl>
请注意,您应该使用Text
代替TextProperty
,并确保将_abc = "20"
更改为_abc = value
。