Search code examples
c#wpfbindingitemscontrolitemspaneltemplate

custom user control binding on itemspaneltemplate


I'm having trouble binding to a custom dependencyproperty on a usercontrol to my MVVM ViewModel. My user control is correctly working when i use it directly on my view:

    <local:CustomControl Mode="{Binding Mode, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  Grid.Row="0">
        <Button x:Name="InfoBox1" Content="Test1" />
        <Button x:Name="InfoBox2" Content="Test2" />
    </local:CustomControl>

But using it as an itemspaneltemplate the binding is not working:

    <ItemsControl Grid.Row="0" ItemsSource="{Binding Equipment}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <local:CustomControl Mode="{Binding Mode, Mode=TwoWay}"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                ...
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

I've tried using a RelativeSource and finding the itemscontrol/view and setting the path to either Mode or DataContext.Mode but I just can't get the binding to work.

Mode is defined as:

    public static readonly DependencyProperty ModeProperty;

    public Modes Mode
    {
        get { return (Modes)this.GetValue(ModeProperty); }
        set { this.SetValue(ModeProperty, value); }
    }

and registered in the constructor of the custom control:

    public CustomControl()
    {
        Mode = Modes.Default;
    }

    static CustomControl()
    {
        ModeProperty = DependencyProperty.Register("Mode", typeof(Modes), typeof(CustomControl), new FrameworkPropertyMetadata(Mode.Default, OnModeChanged));
    }

    private static void OnModeChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        CustomControl ctrl= o as CustomControl ;
        if (ctrl== null) return;

        Modes mode = (Modes)e.NewValue;
        ctrl.Mode = mode;
    }

Do I need to use a workaround to get the control working as the panel template or am I just messing up the binding too bad?

----Edit

The viewmodel part:

    private Modes _mode= Modes.Default;
    public Modes Mode
    {
        get { return _mode; }
        set { _mode= value; NotifyPropertyChanged(); }
    }

    private ObservableCollection<EquipmentViewModel> _equipment;
    public ObservableCollection<EquipmentViewModel> Equipment
    {
        get { return _equipment; }
        set { _equipment = value; NotifyPropertyChanged(); }
    }

----Edit2: I've investigated further and I'm more complexed. I've added the following to both the ItemsPanelTemplate's control and the one directly in the grid.

 Visibility="{Binding Visible, Converter={StaticResource visibilityConverter}}"

Altering this Visible boolean works in both cases. So it appears to only be an issue with the custom DependencyProperty.

Inspecting the visual tree the DataContext of the control as ItemsPanelTemplate is also correct.

What could make the dependency property work properly when used straight and not when used as an itemspaneltemplate ?


Solution

  • Found what was causing the strange conflicting behavior. I was setting the property to a certain value in the normal ctor

    public CustomControl()
    {
        Mode = Modes.Default;
    }
    

    This was appearently causing a conflict when using the control as an Itemspaneltemplate. Removing this made the binding work as expected.

    I guess the difference in behavior has something to do with the calls to the constructor at different times ?