2014-02-18 55 views
1

我试图做一个非常简单的用户控件具有您可以键入文本框,或者您可以通过点击浏览按钮找到一个路径。 我试图用一个依赖属性来做到这一点,但是在绑定到它时这并不完全工作。WPF路径TextBox控件以及浏览按钮,用户控件

这里我的XAML:

<UserControl x:Class="PathSelector.PathSelector" 
     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:PathSelector"> 
    <DockPanel Height="28"> 
     <Button DockPanel.Dock="Right" Padding="5" Margin="5 0 0 0" 
       FontWeight="Bold" 
       Content="..." 
       Click="BrowseButton_Click" /> 
     <Grid> 
      <TextBox 
       HorizontalAlignment="Stretch" VerticalAlignment="Center" 
       x:Name="SelectedPathTxtBox" 
       LostKeyboardFocus="SelectedPathTxtBox_LostKeyboardFocus" /> 
     </Grid>   
    </DockPanel> 
</UserControl> 

这是隐藏代码:

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Input; 

namespace PathSelector 
{ 
    /// <summary> 
    /// A simple input for path, with browse button 
    /// </summary> 
    public partial class PathSelector : UserControl 
    { 
     public PathSelector() 
     { 
      InitializeComponent(); 
     } 


     private void BrowseButton_Click(object sender, RoutedEventArgs e) 
     { 
      System.Windows.Forms.OpenFileDialog fileDialog = new System.Windows.Forms.OpenFileDialog(); 
      fileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*"; 
      if (fileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) 
      { 
       SelectedPathTxtBox.Text = fileDialog.FileName; 
      } 
     } 

     #region Dependency Properties 

     public string SelectedPath 
     { 
      get { return (string)GetValue(SelectedPathProperty); } 
      set { SetValue(SelectedPathProperty, value); } 
     } 

     public static readonly DependencyProperty SelectedPathProperty = 
      DependencyProperty.Register(
      "SelectedPath", 
      typeof(string), 
      typeof(PathSelector), 
      new FrameworkPropertyMetadata(new PropertyChangedCallback(SelectedPathChanged)) 
       { 
        BindsTwoWayByDefault = true, 
        DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged 
       }); 

     private static void SelectedPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      MessageBox.Show("Changed!"); 
      // How to update the values here?? 
     } 

     #endregion    

     private void SelectedPathTxtBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) 
     { 
      SelectedPath = SelectedPathTxtBox.Text; 
     } 
    } 
} 

我想用这个用户控件这样以后:

<pathselector:PathSelector 
    SelectedPath="{Binding PathToSomeFile}"/> 

“PathToSomeFile” 是ViewModel中应该在两个方向上更新的字符串变量。

我该如何做到这一点?我错过了什么?

非常感谢!

+0

'PathToSomeFile'是一个字段或属性? –

+0

'PathToSomeFile'是在实现INotifyPropertyChanged – joerg

回答

1

如下修改SelectedPathChanged

private static void SelectedPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    ((PathSelector)d).SelectedPathTxtBox.Text = e.NewValue.ToString(); 

    MessageBox.Show("Changed!"); 
} 
+0

太棒了!这帮助了我......非常感谢! – joerg

0

如果你只是错过了这两个方向的部分,你可以使用:

<pathselector:PathSelector SelectedPath="{Binding PathToSomeFile, Mode=TwoWay}" /> 

此处了解详情:

MSDN Binding.Mode Property

+0

一个ViewModel的属性我有'BindsTwoWayByDefault = TRUE;设置此默认情况下,在DP – joerg

1

你应该绑定文本框的文本到您的自定义DP这将自动更新其来源属性。

<TextBox HorizontalAlignment="Stretch" VerticalAlignment="Center" 
     x:Name="SelectedPathTxtBox" 
     Text="{Binding SelectedPath, RelativeSource={RelativeSource 
          Mode=FindAncestor, AncestorType=UserControl}}"/> 

你也不需要处理引发LostFocus,因为文字默认UpdateSourceTrigger值为LostFocus。它将更新失去焦点的绑定属性SelectedPath

由于SelectedPath,默认UpdateSourceTrigger值是PropertyChanged,它会更新PathToSomeFile每当属性更改。

+0

非常有用的......会改变的寄存器方法。谢谢! – joerg

+0

就意识到,我不得不添加'模式= TwoWay'和'UpdateSourceTrigger = PropertyChanged'这两个方向上得到更新 – joerg

+0

文本默认'Mode'是'TwoWay'。如果您想更新PropertyChanged上的源值,则需要'UpdateSourceTrigger = PropertyChanged'。但根据你的问题,我以为你想让它在LostFocus上更新。无论如何,如果你想在PropertyChanged上更新,只需设置'UpdateSourceTrigger = PropertyChanged'。 –