0

允許我將問題簡化爲其基本塊。將UserControl綁定到WPF中MainWindow ViewModel的依賴屬性

我在我的項目中有一個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)); 

而且用戶控件的構造函數是簡單地

public UserControl1() 
{ 
    InitializeComponent(); 
    DataContext = this; 
} 

在MainWindow中,我有這個:

<userctrl:UserControl1 TextProperty="{Binding ABC, UpdateSourceTrigger=PropertyChanged}"/> 
<TextBox Grid.Row="1" Text="{Binding PQR, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/> 

現在,在主窗口的視圖模型,我有:

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(); 
      } 
     } 
    } 

現在,即使在用戶控件應該複製無論我在文本框中寫的,對不對?

但它沒有。我爲ABC的制定者設定了斷點。它得到更新,但該更新沒有達到UserControl。我的直覺說綁定失敗了,這是因爲我在UserControl的構造函數中設置了DataContextthis

我該如何解決它?

的實際情景:

下面是用戶控件的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); 
    } 
} 

,這裏是我如何使用它在我的主窗口中:

<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; 
     } 

} 

而現在,視圖模型:

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(); 
     } 
    } 

什麼是預期的功能?

讓我來說明一下。

The Lock

人們可以輸入PIN碼,該散列將顯示在NodeGrid。然後用戶將點擊與散列連接的字母。然後用戶可以點擊解鎖。

回答

1

您應該在UserControl中使用ElementName或使用RaltiveResource找到它,並且不應該使用DataContext = this。(見this answerthis link

給你的用戶控件的名稱並寫:

<UserControl x:Class= ...... 
     Name="userControl"> 
    <TextBox Text="{Binding Text, ElementName = userControl}"/> 
</UserControl> 

請注意,你應該使用Text代替TextProperty並確保改變_abc = "20"_abc = value

+0

對不起'_abc =「20」'。我正在使用它來查看它是否以恆定值工作。 –

+0

也許我給出的問題描述過於簡單。我的情況稍微複雜一點。我編輯了我的問題來說明我的特殊問題。 –

+0

和你的簡單例子一樣。在這部分使用''ElementName'''Text =「{Binding PasswordDisplay,Mode = TwoWay,UpdateSourceTrigger = PropertyChanged}」''。其他的事情似乎很好。 – Ron

相關問題