C# 以浏览按钮作为用户控件的WPF路径文本框

C# 以浏览按钮作为用户控件的WPF路径文本框,c#,wpf,xaml,user-controls,dependency-properties,C#,Wpf,Xaml,User Controls,Dependency Properties,我正在尝试制作一个非常简单的UserControl,它有一个路径,您可以在文本框中键入,也可以通过单击浏览按钮找到。 我尝试使用依赖属性来实现这一点,但绑定到依赖属性时,这并不能完全起作用 这里是我的xaml: <UserControl x:Class="PathSelector.PathSelector" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x=

我正在尝试制作一个非常简单的UserControl,它有一个路径,您可以在文本框中键入,也可以通过单击浏览按钮找到。 我尝试使用依赖属性来实现这一点,但绑定到依赖属性时,这并不能完全起作用

这里是我的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;
        }
    }
}
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Input;
命名空间路径选择器
{
/// 
///一个简单的路径输入,带有浏览按钮
/// 
公共部分类路径选择器:UserControl
{
公共路径选择器()
{
初始化组件();
}
私有无效浏览按钮单击(对象发送者,路由目标)
{
System.Windows.Forms.OpenFileDialog fileDialog=新建System.Windows.Forms.OpenFileDialog();
fileDialog.Filter=“txt文件(*.txt)|*.txt|所有文件(*.*)|*.”;
if(fileDialog.ShowDialog()==System.Windows.Forms.DialogResult.OK)
{
SelectedPathTxtBox.Text=fileDialog.FileName;
}
}  
#区域依赖属性
公共字符串选择路径
{
get{return(string)GetValue(SelectedPathProperty);}
set{SetValue(SelectedPathProperty,value);}
}
公共静态只读从属属性SelectedPathProperty=
从属属性。寄存器(
“SelectedPath”,
类型(字符串),
类型(路径选择器),
新的FrameworkPropertyMetadata(新的PropertyChangedCallback(SelectedPathChanged))
{
BindsTwoWayByDefault=true,
DefaultUpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged
});
私有静态void SelectedPathChanged(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
MessageBox.Show(“已更改!”);
//如何更新此处的值??
}
#端区
private void SelectedPathTxtBox\u LostKeyboardFocus(对象发送器,KeyboardFocusChangedEventArgs e)
{
SelectedPath=SelectedPathTxtBox.Text;
}
}
}
我希望以后像这样使用此UserControl:

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

“PathToSomeFile”是ViewModel中的一个字符串变量,应在两个方向上进行更新

我怎样才能做到这一点?我错过了什么


非常感谢

如果您只是错过了双向部分,可以使用:

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

更多信息请点击此处:


您应该将文本框文本绑定到自定义DP,该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

修改
SelectedPathChanged
,如下所示:

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

    MessageBox.Show("Changed!");
}

PathToSomeFile
是字段还是属性?
PathToSomeFile
是实现InotifyPropertyChange的ViewModel中的属性。默认情况下,我已在DPGreat的register方法中使用
BindsTwoWayByDefault=true
设置此属性!这帮了我。。。谢谢!非常有用。。。这将改变现状。谢谢刚刚意识到我必须添加
Mode=TwoWay
UpdateSourceTrigger=PropertyChanged
两个方向都得到更新文本默认
Mode
TwoWay
。如果您想更新PropertyChanged上的源值,则需要使用
updateSourceTracger=PropertyChanged
。但根据你的问题,我想你希望它是关于LostFocus的更新。无论如何,如果您希望它在PropertyChanged上更新,只需设置
UpdateSourceTrigger=PropertyChanged
。通常情况下,我不知道默认值,并将它们设置为我知道该值的真实值。因为默认情况下,
TwoWay
,所以它在没有设置模式的情况下工作。但是如果没有
UpdateSourceTrigger
,则在使用浏览对话框设置路径时不会更新。(可能是因为我刚刚设置了文本属性!?)是的,米兰的答案是“真正的”解决方案(有效)。你的回答帮助我得到了一些“更干净”的代码。所以谢谢你们两位:)