Home > database >  Properly bind DependencyProperty of UserControl in MVVM
Properly bind DependencyProperty of UserControl in MVVM

Time:08-25

I wanted to create a textbox that can search for files and also keeps track of previously used files. So I made a user control with a DependecyProperty that should give me the current text of the textbox and a button. But everytime I try to bind to the DependencyProperty, the property that binds to it remains empty. In short, the control looks like this:

<UserControl
    <!-- ... -->
    x:Name="PTB">

    <AutoSuggestBox x:Name="SearchBox"
                    Text="{Binding ElementName=PTB, Path=FilePath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

    <Button Command="{Binding PickFileCommand}" />
</UserControl

I have this simple ViewModel for the user control

public string FilePath
{
     get => _filePath;
     set => SetProperty(ref _filePath, value);
}

public async Task PickFile()
{
     // ...
}

and this code-behind for the user control

public readonly static DependencyProperty FilePathProperty =
     DependencyProperty.Register("FilePath", typeof(string), typeof(PathTextBox), new PropertyMetadata("", new PropertyChangedCallback(OnTextChanged)));

public string FilePath
{
     get => (string)GetValue(FilePathProperty);
     set => SetValue(FilePathProperty, value);
}

private static void OnTextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
     if (dependencyObject is PathTextBox ptb && e.NewValue is string s)
     {
          ptb.SearchBox.Text = s;
          ptb.FilePath = s;
     }
}

And when I try to use it like this in my MainPage.xaml:

<customcontrols:PathTextBox x:Name="SearchBox"
                            KeyUp="SearchBox_KeyUp"
                            FilePath="{Binding ScriptFilePath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

and MainPage.xaml.cs

private async void SearchBox_KeyUp(object sender, KeyRoutedEventArgs e)
{
     if (e.Key == VirtualKey.Enter)
     {
          await ViewModel.OpenSqlFile(ViewModel.ScriptFilePath);
     }
}

then ViewModel.ScriptFilePath remains empty, even though I did bind to it. I tried a couple of different things with x:Bind etc., but I couldn't find a way to cleanly implement it in MVVM. I'm using the CommunityToolkit.Mvvm library, if that helps. Any ideas?

CodePudding user response:

From your code, I assume that you have the ViewModel in MainPage.xaml.cs. Then you need to add ViewModel to you binding code.

<customcontrols:PathTextBox
    x:Name="SearchBox"
    KeyUp="SearchBox_KeyUp"
    FilePath="{Binding ViewModel.ScriptFilePath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

or even better, use x:Bind ViewModel.ScriptFilePath.

  • Related