1

I have following ListBox in my WPF application:

<ListBox x:Name="Domaci_soupiska" Margin="0" Background="#FFF1DE8A" AllowDrop="True" Drop="Soupiska_D_drop" Grid.Column="1">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Label Content="{Binding Typ, Mode=TwoWay}" />
                <local:HracControl Hrac="{Binding Hrac, Mode=TwoWay}"/>
                <TextBox Text="{Binding Cas, Mode=TwoWay}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

which ItemsSource is ObservableCollection<SoupiskaRow> where the SoupiskaRow is a simple class:

public class SoupiskaRow
{
    public string Typ { get; set; }
    public Hrac Hrac { get; set; }
    public string Cas { get; set; }
}

and the local:HracControl is a UserControl with dependency property Hrac (pretty much just a storage). However when I add an item to the ObervableCollecion only "default" HracControl is created inside the ListBox - without any data set. Moreover, when I put breakpoint to the set part of Hracdependency property the databinding does not even try to set this property.
The databinding sets the label context or textbox text just fine but I dont understand why it does not even attempt to set a custom property?
I found several threads on similar topic, but they suggested dropping any CustomControls and copy/paste its code into the DataTemplate of ListBox.
Code of HracControl is rather simple:

public Hrac Hrac
    {
        get { return (Hrac)GetValue(HracProperty); }
        set { SetValue(HracProperty, value);}
    }

    public static readonly DependencyProperty HracProperty =
            DependencyProperty.Register("Hrac", typeof(Hrac), typeof(HracControl) , new PropertyMetadata(new Hrac()));

    public HracControl()
    {
        this.InitializeComponent();
        this.DataContext = this;
    }

    public HracControl(Hrac hrac)
    {
        this.InitializeComponent();
        this.Hrac = hrac;
        this.DataContext = this;
    }
//and a methods for reordering/hiding some columns and drag/drop events
}

the inside of xaml:

<Grid x:Name="LayoutRoot">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
...
        </Grid.ColumnDefinitions>
        <Label x:Name="Hrac_ID" Content="{Binding Hrac.Hrac_ID}" HorizontalAlignment="Left" VerticalAlignment="Top"/>
        <Label x:Name="Jmeno" Content="{Binding Hrac.Jmeno}" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="1"/>
...
</Grid>

if you need more code, please let me know in comments

6
  • You will not see wrapper property setter/getter get called for DependencyProperty. It calls directly GetValue and SetValue. As to your problem do you do something like DataContex = this in your HracControl? Commented May 2, 2015 at 20:32
  • Sure, I call DataContex = this; in the constructor. It might be the problem if it call it directly as part of my logic is in the set{}. Commented May 2, 2015 at 20:35
  • 1
    Each FrameworkElement can have only one DataContext. Either inherited through visual tree or set manually. When you set DataContext in control's constructor you change default binding context for control itself and all its children, including <local:HracControl Hrac="{Binding ....}"/>. Post you control code but instead of setting DataContext inside you need to change binding context per binding either via ElementName or RelativeSource binding. Long story short, at the moment you try to bind HracControl.Hrac to HracControl.Hrac Commented May 2, 2015 at 20:38
  • DataTemplate would be the simplier smarter choise here unless the custom control is absolutley necessary. can you post the code for local:HracControl? Commented May 2, 2015 at 20:38
  • @dkozl can you please be more specific how to change it per binding? Commented May 2, 2015 at 20:48

1 Answer 1

1

As mentioned in the comment each FrameworkElement can have only one DataContext. It will be either inherited through visual tree or set manually.

public HracControl(Hrac hrac)
{
    ...
    this.DataContext = this;
}

By doing this you change default binding context for control itself and all its children, including

<local:HracControl Hrac="{Binding Hrac....}"/>. 

So it will search Hrac in HracControl, so it will try to bind HracControl.Hrac to HracControl.Hrac. Instead of setting DataContext manually in constructor you need to change binding context per binding either via ElementName or RelativeSource binding.

<UserControl ... x:Name="myControl">
    <Grid ...>
        <Label x:Name="Hrac_ID" Content="{Binding ElementName=myControl, Path=Hrac.Hrac_ID}" ... />
        <Label x:Name="Jmeno" Content="{Binding ElementName=myControl, Path=Hrac.Jmeno}" .../>
    </Grid>
</UserControl>
Sign up to request clarification or add additional context in comments.

1 Comment

The last part of your comment "Long story short, at the moment you try to bind HracControl.Hrac to HracControl.Hrac" was very helpful. It works now as intended, thanks.

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.