2015-09-26 60 views
-2

我是WPF的新手,尝试从winforms移动,所以这是基本问题,但我试图从按钮单击添加到字符串。该场景基本上是一个键盘按钮(0 - 9),用户按下这些键以输入代码作为一种PIN。这样做的方法是不可谈判的,所以我不能用文本框替换并让用户键入它。我对绑定有一点了解,但是它看起来像是一个字符串的附加字符串,显然,所有按钮(0-9)都需要能够按顺序附加到该字符串。所以无论如何,我有一个名为'EnteredCode'的属性的ViewModel,并且按钮位于名为'buttonsGrid'的网格中。我是否认为我在网格级别处理ButtonBase.Click事件是正确的,确定哪一个被点击,然后附加到字符串?附加到字符串显然是我需要帮助的问题,但正如一般反馈最佳实践一样!添加到按钮上的字符串单击WPF c#

代码示例也是一个巨大的帮助。

TIA

+0

你提到视图模型。你想要做MVVM吗?如果是这样你不会使用Button.Click事件。 – KornMuffin

回答

1

所以,你可以把WPF就像Windows窗体和代码隐藏MainWindow.xaml.cs 实例解决这个问题:

DemonstrationViewModel demoViewModel; 
    public MainWindow() 
    { 
     InitializeComponent(); 
     demoViewModel = new DemonstrationViewModel(); 
     DataContext = demoViewModel; 
    } 

    private void alsoDemoButton_Click(object sender, RoutedEventArgs e) 
    { 
     demoViewModel.EnteredCode += "Clicked"; 
    } 

然而,与视图模型的在声明中提,您可能会遵循MVVM模式,并且不推荐在后面的代码中编写代码。

如果您关注的是MVVM模式,那么ICommands将是一种可行的方法。

伪十岁上下的例子

XAML

<Button x:Name="demoButton" Command="{Binding InsertCommand}"/> 

视图模型

#region Constructor 
    public DemonstrationViewModel() 
    { 
     InsertCommand = new RelayCommand(ExecuteInsert, CanExecuteInsert); 
    } 
    #endregion 

    private void ExecuteInsert() 
    { 
     EnteredCode += "Clicked! "; 
    } 

Further reading on ICommand in MVVM

+0

一个更简单的例子,上面的和进一步的阅读有助于解决问题!谢谢! –

0

你必须努力PasswordBox的密码属性绑定到你的ViewModel财产。密码属性不可绑定,因为它不是一个DependencyProperty。这是出于安全原因。

但是,如果您想使其可绑定,则必须使用自定义的AttachedProperty。现在,您正试图通过按ATM机器上的按钮来输入PIN码,并希望您的密码也可以被绑定。看到下面的示例,让你开始。

XAML代码:

<Window x:Class="WpfEvents._32802407.Win32802407" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:pwd="clr-namespace:PasswordExtras" 
     Title="Win32802407" Height="354.136" Width="385.714"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="143*"/> 
      <ColumnDefinition Width="46*"/> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="16*"/> 
      <RowDefinition Height="19*"/> 
      <RowDefinition Height="32*"/> 
      <RowDefinition Height="95*"/> 
     </Grid.RowDefinitions> 
     <TextBlock TextWrapping="Wrap" Text="Welcome Joshua !" FontSize="18" VerticalAlignment="Center" Margin="10,4,0,4"/> 
     <PasswordBox x:Name="pbPin" pwd:PasswordBoxAssistant.BindPassword="True" pwd:PasswordBoxAssistant.BoundPassword="{Binding Path=PIN, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" Grid.Row="2" VerticalAlignment="Center" Width="120" FontSize="18" BorderThickness="0"/> 
     <StackPanel Grid.Column="1" HorizontalAlignment="Left" Height="170" Margin="10,10,0,0" Grid.Row="3" VerticalAlignment="Top" Width="72"> 
      <Button Content="Done" Margin="0,15,0,0" Height="31"/> 
      <Button Content="Clear" Margin="0,15,0,0" Height="31"/> 
      <Button Content="Cancel" Margin="0,15,0,0" Height="31"/> 
     </StackPanel> 
     <WrapPanel ButtonBase.Click="NumericButtons_Click" HorizontalAlignment="Left" Height="147" Margin="10,23,0,0" Grid.Row="3" VerticalAlignment="Top" Width="266"> 
      <Button Content="1" Width="75" Margin="5" Height="25"/> 
      <Button Content="2" Width="75" Margin="5" Height="25"/> 
      <Button Content="3" Width="75" Margin="5" Height="25"/> 
      <Button Content="4" Width="75" Margin="5" Height="25"/> 
      <Button Content="5" Width="75" Margin="5" Height="25"/> 
      <Button Content="6" Width="75" Margin="5" Height="25"/> 
      <Button Content="7" Width="75" Margin="5" Height="25"/> 
      <Button Content="8" Width="75" Margin="5" Height="25"/> 
      <Button Content="9" Width="75" Margin="5" Height="25"/> 
      <Button Content="0" Width="75" Margin="5" Height="25"/> 
     </WrapPanel> 
     <TextBlock HorizontalAlignment="Left" Margin="23,9,0,0" Grid.Row="1" TextWrapping="Wrap" Text="Enter your pin or press cancel" VerticalAlignment="Top"/>  
    </Grid> 
</Window> 

XAML代码隐藏:

using System; 
using System.Windows; 
using System.Windows.Controls; 

using System.Diagnostics; 

namespace WpfEvents._32802407 
{ 
    /// <summary> 
    /// Interaction logic for Win32802407.xaml 
    /// </summary> 
    public partial class Win32802407 : Window 
    { 
     ViewModelATM atm = new ViewModelATM(); 
     public Win32802407() 
     { 
      InitializeComponent(); 
      this.DataContext = atm; 
     } 

     private void NumericButtons_Click(object sender, RoutedEventArgs e) 
     { 
      string pwd = PasswordExtras.PasswordBoxAssistant.GetBoundPassword(pbPin); 

      if (pwd.Length == 4) 
      { 
       e.Handled = true; 
       return; 
      } 

      pwd = pwd + ((Button)e.OriginalSource).Content; 

      PasswordExtras.PasswordBoxAssistant.SetBoundPassword(pbPin, pwd); 

      Debug.WriteLine(pwd + " : " + atm.PIN); 
     } 
    } 
} 

namespace PasswordExtras 
{ 
    public static class PasswordBoxAssistant 
    { 
     public static readonly DependencyProperty BoundPassword = 
      DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordBoxAssistant), new PropertyMetadata(string.Empty, OnBoundPasswordChanged)); 

     public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached(
      "BindPassword", typeof (bool), typeof (PasswordBoxAssistant), new PropertyMetadata(false, OnBindPasswordChanged)); 

     private static readonly DependencyProperty UpdatingPassword = 
      DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false)); 

     private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      PasswordBox box = d as PasswordBox; 

      // only handle this event when the property is attached to a PasswordBox 
      // and when the BindPassword attached property has been set to true 
      if (d == null || !GetBindPassword(d)) 
      { 
       return; 
      } 

      // avoid recursive updating by ignoring the box's changed event 
      box.PasswordChanged -= HandlePasswordChanged; 

      string newPassword = (string)e.NewValue; 

      if (!GetUpdatingPassword(box)) 
      { 
       box.Password = newPassword; 
      } 

      box.PasswordChanged += HandlePasswordChanged; 
     } 

     private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e) 
     { 
      // when the BindPassword attached property is set on a PasswordBox, 
      // start listening to its PasswordChanged event 

      PasswordBox box = dp as PasswordBox; 

      if (box == null) 
      { 
       return; 
      } 

      bool wasBound = (bool)(e.OldValue); 
      bool needToBind = (bool)(e.NewValue); 

      if (wasBound) 
      { 
       box.PasswordChanged -= HandlePasswordChanged; 
      } 

      if (needToBind) 
      { 
       box.PasswordChanged += HandlePasswordChanged; 
      } 
     } 

     private static void HandlePasswordChanged(object sender, RoutedEventArgs e) 
     { 
      PasswordBox box = sender as PasswordBox; 

      // set a flag to indicate that we're updating the password 
      SetUpdatingPassword(box, true); 
      // push the new password into the BoundPassword property 
      SetBoundPassword(box, box.Password); 
      SetUpdatingPassword(box, false); 
     } 

     public static void SetBindPassword(DependencyObject dp, bool value) 
     { 
      dp.SetValue(BindPassword, value); 
     } 

     public static bool GetBindPassword(DependencyObject dp) 
     { 
      return (bool)dp.GetValue(BindPassword); 
     } 

     public static string GetBoundPassword(DependencyObject dp) 
     { 
      return (string)dp.GetValue(BoundPassword); 
     } 

     public static void SetBoundPassword(DependencyObject dp, string value) 
     { 
      dp.SetValue(BoundPassword, value); 
     } 

     private static bool GetUpdatingPassword(DependencyObject dp) 
     { 
      return (bool)dp.GetValue(UpdatingPassword); 
     } 

     private static void SetUpdatingPassword(DependencyObject dp, bool value) 
     { 
      dp.SetValue(UpdatingPassword, value); 
     } 
    } 
} 

视图模型

using System; 

namespace WpfEvents._32802407 
{ 
    public class ViewModelATM 
    { 
     string _pin = ""; 
     public string PIN { get { return _pin; } set { _pin = value; } } 

    } 
} 
+0

一个非常好的答案,但我认为这对手头的任务来说有点矫枉过正,虽然关于附加属性的示例也有帮助! –

+0

这不是一个矫枉过正的问题,我已经发布了完整的示例解决方案,因为您要求提供示例代码。您需要PasswordBox的附加属性,并且您还需要绑定。你也在你的问题中表示你想处理按钮点击。解决方案根据您的要求发布。 – AnjumSKhan