Loading layout breaks template bindings

2 posts, 0 answers
  1. Nikita
    Nikita avatar
    13 posts
    Member since:
    Jan 2015

    Posted 10 Mar 2015 Link to this post

    Hello. I kind of necroposted in other thread about this issue. That thread seems to be inactive though, so I thought I might as well start a new one, and add some context.

    So, long story short, I am trying to implement MVVM with RadDocking and I am having troubles with data binding. Whenever I call LoadLayout method all the binidings that were set in templates break, and i don't know how to fix them.

    This is the global style, I'm applying to RadPanes:

    <DataTemplate x:Key="HeaderTemplate">
        <StackPanel Orientation="Horizontal">
            <Image Margin="0,0,3,0" Source="{Binding Screen.IconSource}" Width="16" Height="16""/>
            <TextBlock Text="{Binding Screen.Title}"/>
        </StackPanel>
    </DataTemplate>
     
    <Style TargetType="{x:Type Controls:RadPane}">
        <Setter Property="HeaderTemplate" Value="{StaticResource HeaderTemplate}"/>
        <Setter Property="TitleTemplate" Value="{StaticResource HeaderTemplate}"/>
    </Style>

    This is my viewmodel class which represents a single pane:
    public class ScreenViewModel
    {
            public ScreenViewModel(IScreen screen)
            {
                Screen = screen;
            }
     
            public IScreen Screen { get; private set; }
             
            private RadPane _pane;
              //this property is set in DockingPanesFactory.CreatePaneForItem method
            public RadPane Pane
            {
                get { return _pane; }
                set
                {
                    _pane = value;
                    _pane.Content = Screen.View;
                    _pane.Header = this;
                    RadDocking.SetSerializationTag(_pane, Screen.ContentId);
                }
            }
    //+some other irrelevant properties
    }
     
    //this is my model
    interface IScreen
    {
        UIElement View { get; }
        string Title { get; }
        string ContentId { get; }
        ImageSource IconSource { get; }
    }

    And this is how I load the layout:
    public ObservableCollection<ScreenViewModel> Screens { get; set; }
     
    public void Load(string file, IScreenFactory screenFactory)
    {
        if (!File.Exists(file)) return;
        Screens.Clear();
        using (var fs = File.OpenRead(file))
        {
            var doc = XDocument.Load(fs);
            foreach (var screenId in doc.Descendants("RadPane").Select(x => x.Attribute("SerializationTag").Value))
            {
                //some factory wich creates models by their IDs
                IScreen screen = screenFactory.RestoreScreen(screenId);
                Screens.Add(new ScreenViewModel(screen));
            }
            if (Screens.Any())
            {
                fs.Position = 0;
                //after this call all template the bindings break
                _radDocking.LoadLayout(fs);
            }
        }
    }
    After the LoadLayout call I can see that header content is set, and that the template is applied, but the bindings set by this template are broken (VS Output is flooded by binding exceptions), which results in empty pane headers. What am I doing wrong?

  2. Nikita
    Nikita avatar
    13 posts
    Member since:
    Jan 2015

    Posted 11 Mar 2015 Link to this post

    Nevermind, I have figured this one out. In order for header template to work after LoadLayout call, you have to re-set RadPane.Header property in ElemntLoaded event handler. Setting it in DockingPanesFactory.CreatePaneForItem method is not enough, apparently.
  3. UI for WPF is Visual Studio 2017 Ready
Back to Top