Databinding not working on Avalondock window

877 views Asked by At

I have a project with a Window Manager using AvalonDock.

Basically there is two Element : a LayoutAnchorableItem to show my different tool box (currently one, consisting of a Treeview) and a LayoutItem to show the document opened with the treeview (a custom control, with bindable parameters - in theory)

The ViewModel of the DockingManager hosts the ObservableCollection named Panes that will be the LayoutItems.

Things works "fine" if I don't try to bind the parameters in the XAML, and force the values like this

<avalonDock:DockingManager.LayoutItemTemplateSelector>
    <panes:PanesTemplateSelector>
        <panes:PanesTemplateSelector.ExchangeViewTemplate>
            <DataTemplate>
                <xchng:Exchange/>
            </DataTemplate>
        </panes:PanesTemplateSelector.ExchangeViewTemplate>
        <panes:PanesTemplateSelector.GraphViewTemplate>
            <DataTemplate>
                <grph:Graph TickerCode="ILD" ExchangeCode="EPA"/>
            </DataTemplate>
        </panes:PanesTemplateSelector.GraphViewTemplate>
    </panes:PanesTemplateSelector>
</avalonDock:DockingManager.LayoutItemTemplateSelector>

Exchange is the toolbox and Graph is the LayoutItems.

The initial databinding for the docking manager is done like this :

<avalonDock:DockingManager Margin="0,0,0,0" 
                         Grid.Row="1"
                         AnchorablesSource="{Binding Tools}"
                         DocumentsSource="{Binding Panes}" 
                         ActiveContent="{Binding ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}"
                         x:Name="dockManager">

Note that Pane is of type GraphViewModel which has two public parameters : ExchangeCode and TickerCode.

The thing is I want to bind the TickerCode and ExchangeCode to the Panes.TickerCode and Panes.ExchangeCode values.

So I tried this :

<grph:Graph TickerCode="{Binding TickerCode, UpdateSourceTrigger=PropertyChanged}" ExchangeCode="{Binding ExchangeCode, UpdateSourceTrigger=PropertyChanged}"/>

But it does nothing : TickerCode and ExchangeCode in the custom control are equal to "" contrary to when I force the values in the XAML.

Also the somewhat weird thing is that if I step in the code execution, Panes actually have values for TickerCode and ExchangeCode, they just don't bind. For instance, the code that actually create the pane is

public void AddGraph(string FullName, string ExchangeCode, string TickerCode)
    {
        var graphViewModel = new GraphViewModel(FullName, ExchangeCode, TickerCode);
        _panes.Add(graphViewModel);
        ActiveDocument = graphViewModel;

    }

Here, every step has both values. And let's imagine that I add 5 different panes, they are all with their correct ExchangeCode and TickerCode, but nothing is passed to the custom control.

If you need more info on my custom control that values are bound to, here is the code : Passing parameters to custom control (databinding).

Remark: As you see I didn't put much of my code, make request if you think it may help and I will add what's needed. Note that the global logic of the whole window manager is the same provided in the AvalonDock test app (AvalonDock.MVVMTestApp).

1

There are 1 answers

4
Jofta On

For example, if I’ve got ChartView and ChartViewModel: In MainWindow.xaml:

    <xcad:DockingManager x:Name="dockingManager"
                         AnchorablesSource="{Binding Path=Anchorables}"
                         DocumentsSource="{Binding Path=Documents}"
                         ActiveContent="{Binding Path=ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}">

        <xcad:DockingManager.LayoutItemTemplateSelector>
            <selfViewPane:PaneTemplateSelector>
                <selfViewPane:PaneTemplateSelector.ChartViewTemplate>
                    <DataTemplate>
                        <selfViewDocument:ChartView />
                    </DataTemplate>
                </selfViewPane:PaneTemplateSelector.ChartViewTemplate>
            </selfViewPane:PaneTemplateSelector>
        </xcad:DockingManager.LayoutItemTemplateSelector>

        <xcad:DockingManager.LayoutItemContainerStyleSelector>
            <selfViewPane:PaneStyleSelector>
                <selfViewPane:PaneStyleSelector.ChartViewStyle>
                    <Style TargetType="{x:Type xcad:LayoutItem}">
                        <Setter Property="Title" Value="{Binding Model.Title}"/>                                
                        <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}"/>
                        <Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
                        <Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
                    </Style>
                </selfViewPane:PaneStyleSelector.ChartViewStyle>
            </selfViewPane:PaneStyleSelector>
        </xcad:DockingManager.LayoutItemContainerStyleSelector>

        <xcad:DockingManager.LayoutUpdateStrategy>
            <selfViewPane:LayoutInitializer />
        </xcad:DockingManager.LayoutUpdateStrategy>

        <xcad:LayoutRoot>
            <xcad:LayoutPanel Orientation="Horizontal">
                <xcad:LayoutAnchorablePane Name="ToolsPane" DockWidth="200">
                </xcad:LayoutAnchorablePane>
                <xcad:LayoutDocumentPane />
            </xcad:LayoutPanel>
        </xcad:LayoutRoot>                
    </xcad:DockingManager>

And: In ChartViewModel I’ve got property ChartPlotModel:

/// <summary>
/// Gets or sets the ChartPlotModel.
/// </summary>
public PlotModel ChartPlotModel
{
    get
    {
        return this.chartPlotModel;
    }

    set
    {
        if (this.chartPlotModel != value)
        {
            this.chartPlotModel = value;
            this.RaisePropertyChanged("ChartPlotModel");
        }
    }
}

In ChartView I can bind:

<UserControl x:Class="Jofta.Analyzer.UI.Classes.View.Document.ChartView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
             xmlns:oxy="http://oxyplot.org/wpf"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

    <xctk:BusyIndicator IsBusy="{Binding Path=IsBusy}">
        <Grid>
            <oxy:PlotView Model="{Binding ChartPlotModel}" />
        </Grid>
    </xctk:BusyIndicator>

</UserControl>

In this example I’m binding to PlotView from oxyplot, but I think, you can use this pattern. You’ve got GraphViewModel, GraphView and TickerCode and ExchangeCode.