0

I have a MainWindow. It contains an instance of UserControl1 with a TextBox. MainWindow also contains an instance of a Settings class. I would like to bind the TextBox to a string property of the Settings class.

The difficulty is UserControl1 has no knowledge of MainWindow or Settings (since I want to use UserControl1 in multiple projects). So I made an interface IString, and I pass that to UserControl1. However, I still can't get any binding to work. I realize I'll have to add INotifyPropertyChanged at some point, but I don't think that's what's preventing it from working here.

public interface IString
{
    string String { get; set; }
}

public class Settings : IString
{
    public string String { get; set; }
}

MainWindow XAML:

<Window x:Class="WpfApp1.MainWindow">
    <local:UserControl1 x:Name="TheUserControl"/>
</Window>

and codebehind:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        TheUserControl.Settings = new Settings();
    }
}

UserControl1 XAML:

<UserControl x:Class="WpfApp1.UserControl1"
    <TextBox DataContext="Settings" Text="{Binding String}"/>
</UserControl>

and codebehind:

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

    public IString Settings { get; set; }
}
Craig W
  • 4,390
  • 5
  • 33
  • 51
  • You could read the settings into a proper view model and allow the data context to flow through the window and its children. – Crowcoder Aug 14 '18 at 20:54
  • You could make the setting a bindable property and set it when you use the control on MainWindow – JSteward Aug 14 '18 at 20:56
  • 2
    Declare a [dependency property](https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/custom-dependency-properties) in your UserControl and bind it to the String property of the Settings class. Something like this: https://stackoverflow.com/a/40184402/1136211 – Clemens Aug 14 '18 at 21:00

1 Answers1

1

What you want to do is make it so the property in your UserControl is bindable from the MainWindow. To do this make it a dependency property. Also, as @Clemens suggested you can add a property chnanged call back to execute other code when your property changes. In addtion you can also set the default property and configure other call backs as well, see here for more info

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

    public static readonly DependencyProperty SettingsProperty 
        = DependencyProperty.Register("Settings", typeof(string), typeof(UserControl1),
            new PropertyMetadata(
                "DefaultSetting",
                new PropertyChangedCallback(OnSettingsChanged)));

    public string Settings
    {
        get { return (string)GetValue(SettingsProperty); }
        set { SetValue(SettingsProperty, value); }
    }

    private static void OnSettingsChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var control = (UserControl1)d;
        var newSettings = (string)e.NewValue;
        //Optionally do something when Settings changed
    }
}

Then in the MainWindow

<Window x:Class="WpfApp1.MainWindow">
    <local:UserControl1 x:Name="TheUserControl" Settings="{Binding xyz}"/>
</Window>
Clemens
  • 123,504
  • 12
  • 155
  • 268
JSteward
  • 6,833
  • 2
  • 21
  • 30