2

I have a custom UserControl with a DataGrid and a TextBox, I am trying to databind things to these elements using DependencyProperties. The binding works fine for the DataGrid but not for the TextBox.

Code:

public static readonly DependencyProperty BuiDataProperty = DependencyProperty.Register("BuiData", typeof(IEnumerable), typeof(BelastingTab), new PropertyMetadata(default(IEnumerable), BuiDataChanged));

private static void BuiDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var Object = d as BelastingTab;
    if (Object == null) return;
    Object.BuiDataDataSourceChanged(d, e);
}

private void BuiDataDataSourceChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
    BuiDataTabel.ItemsSource = dependencyPropertyChangedEventArgs.NewValue as IEnumerable;
}

public IEnumerable BuiData
{
    get { return (IEnumerable)GetValue(BuiDataProperty); }
    set { SetValue(BuiDataProperty, value); }
}

And in the main XAML:

<src:BelastingTab BuiData="{Binding Path=Static.BuienRegulier[0].BuiTabel}"/>

This is the code for setting the binding of the DataGrid, how would I go about doing the same for the TextBox?

EDIT: This is what I have currently,

Main XAML:

<src:BelastingTab BuiData="{Binding Path=Static.BuienRegulier[0].BuiTabel}" HerhalingsTijd="{Binding Path=Static.BuienRegulier[0].HerhalingsTijd}"/>

This refers to a string. In the UserControl XAML:

<TextBox Text="{Binding HerhalingsTijd, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

In the UserControl XAML CS:

public static readonly DependencyProperty HerhalingsTijdProperty = DependencyProperty.Register("HerhalingsTijd", typeof(string), typeof(BelastingTab), new PropertyMetadata(string.Empty));

public string HerhalingsTijd
{
    get { return (string)GetValue(HerhalingsTijdProperty); }
    set { SetValue(HerhalingsTijdProperty, value); }
}

1 Answer 1

3

I see no problem in doing what you want. I created a simple test application. I will provide here the code, hope it will help you somehow to fix what you have wrong.

The UserControl1 code:

public partial class UserControl1 : UserControl
{
    public static DependencyProperty TxtBoxValueProperty = DependencyProperty.Register("TxtBoxValue", typeof(String), typeof(UserControl1));

    public String TxtBoxValue
    {
        get { return (String)GetValue(TxtBoxValueProperty); }
        set 
        {
            SetValue(TxtBoxValueProperty, value);
        }
    }

    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);
        if (e.Property == TxtBoxValueProperty)
        {
            // Do whatever you want with it
        }
    }

    public UserControl1()
    {
        InitializeComponent();
    }
}

User control Xaml:

<StackPanel>
    <TextBox Text="{Binding TxtBoxValue, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource AncestorType=UserControl, AncestorLevel=1}, Mode=TwoWay}" Width="100" Height="50"/>
    <TextBox></TextBox>
</StackPanel>

Main window xaml:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    xmlns:local="clr-namespace:WpfApplication1"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
    <local:UserControl1 TxtBoxValue="{Binding TextBoxValue, Mode=TwoWay}"></local:UserControl1>
</Grid>

Main window code behind:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    CancellationTokenSource cTS;
    CancellationToken cT;

    private String _textBoxValue;
    public String TextBoxValue
    {
        get { return _textBoxValue; }
        set 
        {
            _textBoxValue = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("TextBoxValue"));
            }

            if (_textBoxValue.Contains("enough"))
            {
                cTS.Cancel();
            }
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        cTS = new CancellationTokenSource();
        cT = cTS.Token;
        Task.Factory.StartNew(ChangeTextBoxValue, cT);
    }

    public void ChangeTextBoxValue()
    {
        while (true)
        {
            Random rnd = new Random(DateTime.Now.Millisecond);
            TextBoxValue = (rnd.NextDouble() * 1000.0).ToString();
            Thread.Sleep(10000);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Note that I have written this very fast and did how I usually use it (except notify that I put in a ViewModelBase).

If this doesn't work in your case, it is either I did not understand the question, or you have something very specific, but I doubt that.

Sign up to request clarification or add additional context in comments.

3 Comments

I posted an edit with what I have, which doesnt work
After adding your RelativeSource it works, could you explain to me what this does?
The relative source is needed because it is the only way you can access the code behind class properties from a user control. You don't have a data context in the control, so either you make data context to Self, or you access the property from code behind using relative source, so the binding knows from where to get the property. You need a bit of experimenting and reading to fully understand this

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.