-
Notifications
You must be signed in to change notification settings - Fork 337
Closed
Description
In my app, we update the buttons in a ribbon control based upon the state of the last actived document. This works perfectly, until you remove a document. The newly selected document is activated on the UI side, but it is not activated programmatically, causing the bindings to be set according the new situation.
Test code:
WPF MainWindow:
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
xmlns:xcad="https://github.com/Dirkster99/AvalonDock"
mc:Ignorable="d"
d:DataContext="{x:Type local:AppViewModel}"
Title="MainWindow" Height="450" Width="800">
<DockPanel>
<Button Content="Click me" DockPanel.Dock="Top" IsEnabled="{Binding ActiveDocument.IsEnabled}" />
<xcad:DockingManager DocumentsSource="{Binding Documents, Mode=TwoWay}"
AnchorablesSource="{Binding Path=ActiveDocument.ToolPanes}"
ActiveContent="{Binding ActivePane, Mode=TwoWay}"
>
<DockingManager.DocumentHeaderTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="TitleText" Grid.Column="1" Margin="1,0,1,0" MaxWidth="200"
Text="{Binding Content.Title, FallbackValue=#ERROR#}"
ToolTip="{Binding Content.Title}" TextTrimming="CharacterEllipsis"/>
</Grid>
</DataTemplate>
</DockingManager.DocumentHeaderTemplate>
<DockingManager.LayoutItemTemplate>
<DataTemplate>
<Label Content="{Binding Content.Text}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Background="LightBlue" />
</DataTemplate>
</DockingManager.LayoutItemTemplate>
</xcad:DockingManager>
</DockPanel>
</Window>
Models:
using System.Collections.ObjectModel;
using System.Windows;
namespace WpfApp2
{
public class AppViewModel : DependencyObject
{
public static readonly DependencyProperty DocumentsProperty = DependencyProperty.Register(nameof(Documents), typeof(ObservableCollection<Document>), typeof(AppViewModel));
public static readonly DependencyProperty ActiveDocumentProperty = DependencyProperty.Register(nameof(ActiveDocument), typeof(Document), typeof(AppViewModel));
public static readonly DependencyProperty ActivePaneProperty = DependencyProperty.Register(nameof(ActivePane), typeof(ISomeAvalonDockControl), typeof(AppViewModel), new PropertyMetadata(ActivePane_PropertyChanged));
private static void ActivePane_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is AppViewModel self)
{
if (e.NewValue is Document dvm)
{
self.ActiveDocument = dvm;
}
else if (e.NewValue == null)
{
self.ActiveDocument = null;
}
}
}
public ObservableCollection<Document> Documents
{
get { return (ObservableCollection<Document>)this.GetValue(DocumentsProperty); }
set { this.SetValue(DocumentsProperty, value); }
}
public Document ActiveDocument
{
get { return (Document)this.GetValue(ActiveDocumentProperty); }
set { this.SetValue(ActiveDocumentProperty, value); }
}
public ISomeAvalonDockControl ActivePane
{
get { return (ISomeAvalonDockControl)this.GetValue(ActivePaneProperty); }
set { this.SetValue(ActivePaneProperty, value); }
}
}
public class Document : DependencyObject, ISomeAvalonDockControl
{
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(Document));
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(nameof(Text), typeof(string), typeof(Document));
public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.Register(nameof(IsEnabled), typeof(bool), typeof(Document));
public static readonly DependencyProperty ToolPanesProperty = DependencyProperty.Register(nameof(ToolPanes), typeof(ObservableCollection<ToolPane>), typeof(Document));
public string Title
{
get { return (string)this.GetValue(TitleProperty); }
set { this.SetValue(TitleProperty, value); }
}
public string Text
{
get { return (string)this.GetValue(TextProperty); }
set { this.SetValue(TextProperty, value); }
}
public bool IsEnabled
{
get { return (bool)this.GetValue(IsEnabledProperty); }
set { this.SetValue(IsEnabledProperty, value); }
}
public ObservableCollection<ToolPane> ToolPanes
{
get { return (ObservableCollection<ToolPane>)this.GetValue(ToolPanesProperty); }
set { this.SetValue(ToolPanesProperty, value); }
}
}
public class ToolPane : DependencyObject, ISomeAvalonDockControl
{
}
public interface ISomeAvalonDockControl
{ }
}
I would expect ActivePane to be updated when a tab is closed. It doesn't and remains null after the it was set to null when closing the previous active document.
To see this visually, do the following:
- Start the app.
- Select the second document (it is the first document with true in its name). It should enable the button on top.
- Close the second document .
- The UI gets updated: another document is shown, but the button keeps its old state.
I have made a fix already, but you can argue what document should be activated, and if this is the right place to update the state. I will leave that to you.
monty241
Metadata
Metadata
Assignees
Labels
No labels