twiner
twiner
CC#
Created by twiner on 12/22/2022 in #help
❔ Custom DataTemplate for TextElements or alternative approaches
In WPF I'm working on a customized RichTextBox that will add TextElements that are bound to view models. I want to DataTemplates for this, but you can't put TextElements in a DataTemplate. I've been looking into DataTemplate and FrameworkTemplate to see how they work, but its quite involved and maybe I'm over thinking this. I want to be able to supply, in xaml preferably, a collection of mappings between a partially configure DataType and a template that will be bound to it. This is the code I have for the association at the moment, making a copy of the DataContext is easy enough, but I don't know a what to do to make a copy of the ElementTemplate and maintain the binding information.
<x:Array x:Key="DetailTypes" Type="{x:Type v:ContextOption}">
<v:ContextOption DisplayName="Header">
<v:ContextOption.DataContext>
<m:AddDescriptionDetail Style="Header" />
</v:ContextOption.DataContext>
<v:ContextOption.ElementTemplate>
<rt:Header Text="{Binding Path=Description}"/>
</v:ContextOption.ElementTemplate>
</v:ContextOption>
</x:Array>
<x:Array x:Key="DetailTypes" Type="{x:Type v:ContextOption}">
<v:ContextOption DisplayName="Header">
<v:ContextOption.DataContext>
<m:AddDescriptionDetail Style="Header" />
</v:ContextOption.DataContext>
<v:ContextOption.ElementTemplate>
<rt:Header Text="{Binding Path=Description}"/>
</v:ContextOption.ElementTemplate>
</v:ContextOption>
</x:Array>
[ContentProperty(nameof(ElementTemplate))]
public class ContextOption
{
public IShallowCloner DataContext { get; set; }
public string DisplayName { get; set; }
public TextElement ElementTemplate { get; set; }
}
[ContentProperty(nameof(ElementTemplate))]
public class ContextOption
{
public IShallowCloner DataContext { get; set; }
public string DisplayName { get; set; }
public TextElement ElementTemplate { get; set; }
}
4 replies
CC#
Created by twiner on 12/21/2022 in #help
Sanity check on WPF CustomControl Binding to ViewModel not working
Can someone sanity check me here... In WPF I have a custom control derived from RichTextBox. I needed to have a way to access the selected text from my ViewModel so I could use it to inject into a new object created by said VM However, the value doesn't seem to move across the binding into the view model. So on my view model I made a SelectedText Property
public class MyViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler? PropertyChanged;
private string _selectedText;
public string SelectedText {
get => _selectedText;
set { _selectedText = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedText))); }
}
}
public class MyViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler? PropertyChanged;
private string _selectedText;
public string SelectedText {
get => _selectedText;
set { _selectedText = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedText))); }
}
}
and in my custom RichTextBox I have a DependencyProperty
public class AlertTextBox: RichTextBox {
public static readonly DependencyProperty SelectedTextProperty = DependencyProperty.Register(nameof(SelectedText), typeof(string), typeof(AlertTextBox));
public string SelectedText
{
get => (string)GetValue(SelectedTextProperty);
set => SetValue(SelectedTextProperty, value);
}
public AlertTextBox(){
Selection.Changed += SelectionChanged;
}
public void SelectionChanged(object sender, EventArgs e) => SetCurrentValue(SelectedTextProperty, Selection.Text);
}
public class AlertTextBox: RichTextBox {
public static readonly DependencyProperty SelectedTextProperty = DependencyProperty.Register(nameof(SelectedText), typeof(string), typeof(AlertTextBox));
public string SelectedText
{
get => (string)GetValue(SelectedTextProperty);
set => SetValue(SelectedTextProperty, value);
}
public AlertTextBox(){
Selection.Changed += SelectionChanged;
}
public void SelectionChanged(object sender, EventArgs e) => SetCurrentValue(SelectedTextProperty, Selection.Text);
}
Finally, in my test Window I have it bound together
<AlertTextBox SelectedText="{Binding Path=SelectedText}" />
<AlertTextBox SelectedText="{Binding Path=SelectedText}" />
When inspecting the UI with Snoop, I can see that the binding on SelectedText is considered valid. I believe that using SetCurrentValue is correct to allow the value to propagate across the binding to the ViewModel So I must be missing something, I've done this what feels like countless times and I just don't see what I'm overlooking
10 replies