I am working on MDI application with documents tabs and panels (like in Visual Studio), using AvalonDock 2 + Caliburn.Micro + Fody.PropertyChanged. I want to expand LayoutAnchorable from code (like this works in Visual Studio when you start search in project: panel with search results in bottom of screen expands automatically).
According to MVVM approach I made behavior, bound IsActive property of LAyoutAnchorable - and it doesn't work. More precisely, it works only in one direction: I received notification in ViewModel (when panel opened by user click), but I'm not able to open panel from code. Here is the code. Thanks.
View:
<xcad:LayoutRoot.BottomSide>
<xcad:LayoutAnchorSide>
<xcad:LayoutAnchorGroup>
<xcad:LayoutAnchorable x:Name="ErrorsListPanel" Title="Errors List" AutoHideHeight="300">
<i:Interaction.Behaviors>
<behaviors:LayoutAnchorableBehaviour IsLayoutActive="{Binding IsErrorsListActive,
Mode=OneWay,
UpdateSourceTrigger=PropertyChanged}"/>
</i:Interaction.Behaviors>
<ListView caliburn:Message.Attach="[Event SelectionChanged] = [Action BrowseError($this)]" ItemsSource="{Binding ErrorsList}">
<ListView.Resources>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Left" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Width="500"
DisplayMemberBinding="{Binding Path=File.RelPath}"
Header="File" />
<GridViewColumn Width="500"
DisplayMemberBinding="{Binding Path=Message}"
Header="Description" />
<GridViewColumn Width="50"
DisplayMemberBinding="{Binding Path=Line}"
Header="Line" />
<GridViewColumn Width="50"
DisplayMemberBinding="{Binding Path=Column}"
Header="Column" />
</GridView>
</ListView.View>
</ListView>
</xcad:LayoutAnchorable>
...
....
Behavior:
public sealed class LayoutAnchorableBehaviour : Behavior<LayoutAnchorable>
{
public static readonly DependencyProperty IsLayoutActiveProperty =
DependencyProperty.Register("IsLayoutActive", typeof(bool), typeof(LayoutAnchorableBehaviour),
new FrameworkPropertyMetadata(default(bool), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
(dependencyObject, dependencyPropertyChangedEventArgs) =>
{
var behavior = dependencyObject as LayoutAnchorableBehaviour;
var layout = behavior?.AssociatedObject as LayoutAnchorable;
if (layout == null) return;
layout.IsActive = (bool) dependencyPropertyChangedEventArgs.NewValue;
}));
public bool IsLayoutActive
{
get { return (bool)GetValue(IsLayoutActiveProperty); }
set { SetValue(IsLayoutActiveProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
if (AssociatedObject != null)
{
AssociatedObject.IsActiveChanged += AssociatedObject_IsActiveChanged;
}
}
private void AssociatedObject_IsActiveChanged(object sender, EventArgs e)
{
var layout = sender as LayoutAnchorable;
if (layout != null)
{
IsLayoutActive = layout.IsActive;
}
}
protected override void OnDetaching()
{
base.OnDetaching();
if (AssociatedObject != null)
{
AssociatedObject.IsActiveChanged -= AssociatedObject_IsActiveChanged;
}
}
}
ViewModel:
[ImplementPropertyChanged]
public class ProjectViewModel : Screen
{
public bool IsErrorsListActive { get; set; }
...
public void BrowseErrorsCommand()
{
IsErrorsListActive = true;
}
}
UPD1: lambda-function in dependency property IsLayoutActiveProperty not calls by IsErrorsListActive = true in ViewModel. Maybe this can help.