简体   繁体   中英

UserControl Property Binding not Updating the DataContext

I've created this simple reusable control to browse files.

Then I did a model and implemented the OnPropertyChanged and used the control in MainWindow.

When I click the Browse button in the UserControl the DependencyProperty "FilePath" is correctly set (and the textbox gets the path string) but the model doesn't seem to work.

Additional info : If i use a normal textbox instead of the UserControl ad i do

<TextBox Text="{Binding InputFile}"/>

the model is updated correctly when i type something in the box. If I type something manually in the UserControl (instead than filling it trough the Browse button it doesn't work anyway)

This is the code for the UserControl, the property is set correctly within the control :

public partial class FileBrowserTextBox : UserControl
{
    public FileBrowserTextBox()
    {
        InitializeComponent();
    }

    // FilePath
    public static readonly DependencyProperty FilePathProperty =
        DependencyProperty.Register("FilePath", typeof(string), typeof(FileBrowserTextBox), new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(OnFilePathPropertyChanged)));

    public string FilePath
    {
        get { return (string)GetValue(FilePathProperty); }
        set { SetValue(FilePathProperty, value); }
    }
    static void OnFilePathPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        var obj = o as FileBrowserTextBox;
        if (obj == null)
            return;
    }
    private void BrowseButton_Click(object sender, RoutedEventArgs e)
    {
        // Create OpenFileDialog 
        Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
        // Set filter for file extension and default file extension 
        dlg.DefaultExt = ".txt";
        dlg.Filter = "TXT Files (*.txt)|*.txt|All Files (*.*)|*.*";
        // Display OpenFileDialog by calling ShowDialog method 
        Nullable<bool> result = dlg.ShowDialog();
        // Get the selected file name and display in a TextBox 
        if (result == true)
        {
            // Open document 
            string filename = dlg.FileName;
            FilePath = filename; // this works and updates the textbox
        }
    }
}

And this an extract of the XAML:

<UserControl x:Class="DrumMapConverter.FileBrowserTextBox">
        ...
        <Button Content=" ... " Click="BrowseButton_Click"/>
        <TextBox Name="txtFilepath" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath}"/>
        ...
</UserControl>

This is the model I am using with the INotifyPropertyChanged :

public class DrumMapConverterDataModel :INotifyPropertyChanged
{
    public string InputFile
    {
        get { return inputFile; }
        set
        {
            inputFile = value;
            OnPropertyChanged("InputFile");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    // Create the OnPropertyChanged method to raise the event 
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    private string inputFile;
}

This is the MainWindow class

public partial class MainWindow : Window
{
    private DrumMapConverterDataModel model;
    public MainWindow()
    {
        InitializeComponent();
        model = new DrumMapConverterDataModel();
        DataContext = model;
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(model.InputFile); // if i break here the model has no data changed (InputFile is null)
    }
}

This is how i use the 2 controls (2 examples none of them works) :

<cust:FileBrowserTextBox  Label="Input File" FilePath="{Binding InputFile}"/>
<cust:FileBrowserTextBox  Label="Input File" FilePath="{Binding Path=InputFile, Mode=TwoWay, 
                       RelativeSource={RelativeSource FindAncestor, 
                           AncestorType=Window}}"/>

Any help would be really appreciated.

UPDATE AND SOLUTION :

As suggested from @AnatoliyNikolaev (thanks to his explanation on UpdareSourceTrigger) and @Karuppasamy in the User Control it can be done like this (use the UpdateSourceTrigger explicitly because it's a textbox):

<TextBox Grid.Column="2" Name="txtFilepath" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath, UpdateSourceTrigger=PropertyChanged}"/>

Then the DependencyProperty can be like this (note the BindsTwoWayByDefault ):

public static readonly DependencyProperty FilePathProperty =
    DependencyProperty.Register("FilePath", typeof(string), typeof(FileBrowserTextBox), new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(OnFilePathPropertyChanged)) { BindsTwoWayByDefault = true });

so finally in the MainWindow i can simply write this :

<cust:FileBrowserTextBox  FilePath="{Binding Path=InputFile}" />

Try for your dependency property set UpdateSourceTrigger to PropertyChanged :

The default is Default , which returns the default UpdateSourceTrigger value of the target dependency property. However, the default value for most dependency properties is PropertyChanged , while the Text property has a default value of LostFocus .

Example:

<local:FileBrowserTextBox FilePath="{Binding Path=InputFile, 
                                             Mode=TwoWay,
                                             UpdateSourceTrigger=PropertyChanged}" />

Hope I understood your problem,

I have tried the same and have set the UpdateSourceTrigger to PropertyChanged while binding the TextBox in the UserControl's XAML code. Below is my code,

 <TextBox Width="200" Name="txtFilepath" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=FilePath, UpdateSourceTrigger=PropertyChanged}"/>
    <Button Width="40" Content=" ... " Click="BrowseButton_Click"/>

And it is working.

Thanks

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM