USERCORTROL与WPF中的MainWindow ViewModel的绑定依赖性属性



允许我将问题简化为基本块。

我的项目中有一个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

相关内容

  • 没有找到相关文章