Reputation: 757
I am trying to make a very easy UserControl that has a path that you can type in a textbox or that you can find by clicking a browse button. I tried to do this with a dependency property but this doesn't work completely when binding to it.
Here my 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>
And this is the codebehind:
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;
}
}
}
I want to use this UserControl like this later:
<pathselector:PathSelector
SelectedPath="{Binding PathToSomeFile}"/>
"PathToSomeFile" is a string variable in the ViewModel that should be updated in both directions.
How can I achieve this? What am I missing?
Thanks a lot!
Upvotes: 2
Views: 8157
Reputation: 747
If you just miss the both direction part, you can use:
<pathselector:PathSelector SelectedPath="{Binding PathToSomeFile, Mode=TwoWay}" />
More info here:
Upvotes: 0
Reputation: 1890
Modify SelectedPathChanged
as below:
private static void SelectedPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((PathSelector)d).SelectedPathTxtBox.Text = e.NewValue.ToString();
MessageBox.Show("Changed!");
}
Upvotes: 2
Reputation: 81253
You should bind TextBox Text to your custom DP which will automatically update its source property.
<TextBox HorizontalAlignment="Stretch" VerticalAlignment="Center"
x:Name="SelectedPathTxtBox"
Text="{Binding SelectedPath, RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType=UserControl}}"/>
Also you don't need to handle LostFocus, since Text default UpdateSourceTrigger
value is LostFocus
. It will update the binding property SelectedPath
on lost focus.
And since SelectedPath
, default UpdateSourceTrigger
value is PropertyChanged
, it will update PathToSomeFile
whenever property changes.
Upvotes: 1