The DocumentDock.ItemsSource
property enables automatic document management by binding to a collection of data objects. This functionality provides a clean, MVVM-friendly approach to managing documents within a dock.
DocumentDock.ItemsSource
works similarly to ListBox.ItemsSource
in Avalonia, automatically creating and managing documents from a bound collection. When you add or remove items from the collection, the corresponding documents are automatically created or removed from the dock.
ObservableCollection<T>
in ViewModelsCreate a model class to represent your document data:
public class FileDocument : INotifyPropertyChanged
{
private string _title = "";
private string _content = "";
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
public string Content
{
get => _content;
set => SetProperty(ref _content, value);
}
public bool CanClose { get; set; } = true;
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
Create a ViewModel with an ObservableCollection
of your document models:
public class MainViewModel : INotifyPropertyChanged
{
public ObservableCollection<FileDocument> Documents { get; } = new();
public ICommand AddDocumentCommand { get; }
public ICommand RemoveDocumentCommand { get; }
public MainViewModel()
{
AddDocumentCommand = new Command(AddDocument);
RemoveDocumentCommand = new Command<FileDocument>(RemoveDocument);
// Add some initial documents
Documents.Add(new FileDocument
{
Title = "Welcome.txt",
Content = "Welcome to the application!"
});
}
private void AddDocument()
{
Documents.Add(new FileDocument
{
Title = $"Document {Documents.Count + 1}.txt",
Content = "New document content"
});
}
private void RemoveDocument(FileDocument document)
{
Documents.Remove(document);
}
}
Bind the collection to DocumentDock.ItemsSource
and define a DocumentTemplate
:
<DocumentDock ItemsSource="{Binding Documents}">
<DocumentDock.DocumentTemplate>
<DocumentTemplate>
<StackPanel Margin="10" x:DataType="Document">
<TextBlock Text="Document Properties" FontWeight="Bold" Margin="0,0,0,10"/>
<TextBlock Text="Title:" FontWeight="SemiBold"/>
<TextBox Text="{Binding Context.Title}" Margin="0,0,0,10"/>
<TextBlock Text="Content:" FontWeight="SemiBold"/>
<TextBox Text="{Binding Context.Content}"
AcceptsReturn="True"
TextWrapping="Wrap"
Height="200"/>
</StackPanel>
</DocumentTemplate>
</DocumentDock.DocumentTemplate>
</DocumentDock>
The system automatically maps properties from your model to Document
properties:
Model Property | Document Property | Description |
---|---|---|
Title |
Title |
Tab title display |
Name |
Title |
Alternative to Title |
DisplayName |
Title |
Alternative to Title |
CanClose |
CanClose |
Controls if tab can be closed |
public class DocumentModel
{
// Any of these will be used for the tab title (in order of preference):
public string Title { get; set; } // First choice
public string Name { get; set; } // Second choice
public string DisplayName { get; set; } // Third choice
// Controls whether the tab can be closed
public bool CanClose { get; set; } = true;
}
In DocumentTemplate
, your model is accessed through the Context
property:
<DocumentTemplate>
<Grid x:DataType="Document">
<!-- Access your model properties via Context -->
<TextBlock Text="{Binding Context.Title}"/>
<TextBox Text="{Binding Context.Content}"/>
<!-- You can also access Document properties directly -->
<TextBlock Text="{Binding Title}"/>
</Grid>
</DocumentTemplate>
public class FileModel : INotifyPropertyChanged
{
public string Name { get; set; } // Becomes tab title
public string FilePath { get; set; }
public string Content { get; set; }
public bool IsDirty { get; set; }
public bool IsReadOnly { get; set; }
public bool CanClose => !IsDirty; // Prevent closing unsaved files
public ICommand SaveCommand { get; }
public ICommand RevertCommand { get; }
}
public class SettingsPage : INotifyPropertyChanged
{
public string Title { get; set; } // Tab title
public string Category { get; set; }
public string Icon { get; set; }
public Dictionary<string, object> Settings { get; set; } = new();
public bool CanClose { get; set; } = true;
}
public class DataView : INotifyPropertyChanged
{
public string DisplayName { get; set; } // Tab title
public ObservableCollection<object> Data { get; set; } = new();
public string Filter { get; set; } = "";
public bool CanClose { get; set; } = true;
public ICommand RefreshCommand { get; }
public ICommand ExportCommand { get; }
}
public class DynamicDocument : INotifyPropertyChanged
{
public string Title { get; set; }
public DocumentType Type { get; set; }
public object Data { get; set; }
public bool CanClose { get; set; } = true;
}
public enum DocumentType
{
Text,
Image,
Chart,
Table
}
<DocumentDock ItemsSource="{Binding Documents}">
<DocumentDock.DocumentTemplate>
<DocumentTemplate>
<ContentControl x:DataType="Document">
<ContentControl.Content>
<MultiBinding Converter="{StaticResource DocumentTypeConverter}">
<Binding Path="Context.Type"/>
<Binding Path="Context.Data"/>
</MultiBinding>
</ContentControl.Content>
</ContentControl>
</DocumentTemplate>
</DocumentDock.DocumentTemplate>
</DocumentDock>
public class CommandDocument : INotifyPropertyChanged
{
public string Title { get; set; }
public ICommand CloseCommand { get; }
public ICommand SaveCommand { get; }
public bool CanClose { get; set; } = true;
public CommandDocument()
{
CloseCommand = new Command(() => {
// Custom close logic
var parent = GetParentCollection();
parent?.Remove(this);
});
SaveCommand = new Command(Save);
}
private void Save()
{
// Save logic
}
}
DocumentTemplate
lightweight for better performanceDocuments not appearing:
ItemsSource
is properly boundINotifyCollectionChanged
(use ObservableCollection
)DocumentTemplate
is definedTitle not showing:
Title
, Name
, or DisplayName
propertyTemplates not updating:
INotifyPropertyChanged
in your modelContext.PropertyName
Tabs not closable:
CanClose = true
in your model (default behavior)