I'm using a ComboBox (WPF 4.0) to show user defined paragraph styles for an editor app. The ComboBox has two columns:
(1) Unformatted name of the paragraph style
(2) Text "abcABC123", in some properties formatted according to the paragraph style in the first column
These are public properties of the user defined paragraph style class (where the last 3 are no ResourceKeys but variables containing ResourceKeys):
_NameInternal
_NameUI
_ResourceKey_background
_ResourceKey_foreground
_ResourceKey_fontFamily
Problem: ComboBox shows a SelectedItem. If I open a dialog, change one or more of the three Binding properties of the SelectedItem (Background, Foreground, FontFamily) and close dialog then the SelectedItem of the ComboBox is not updated. But if I drop it down it shows the new formatting.
Is there a way to solve this in Xaml instead of C#?
<Window.Resources>
<local2:_2StylesPara x:Key="_2stylesPara" />
<CollectionViewSource x:Key="_collectionViewSource_stylesPara" Source="{StaticResource _2stylesPara}">
<CollectionViewSource.SortDescriptions>
<!-- Requires 'xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"' declaration. -->
<scm:SortDescription PropertyName="_NameUI" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</Window.Resources>
<ComboBox Name="_cbStylesPara" HorizontalAlignment="Left"
ItemsSource="{Binding Source={StaticResource _collectionViewSource_stylesPara}}"
SelectedValuePath="_NameInternal" IsSynchronizedWithCurrentItem="True" >
<ComboBox.Resources>
<local2:_2ResourceLookupConverter x:Key="_resourceLookupConverter"/>
</ComboBox.Resources>
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="{Binding _NameUI}" Grid.Column="0" VerticalAlignment="Center" />
<TextBlock Grid.Column="1" Text="abcABC123" Margin="3,0,0,0"
Background="{Binding _ResourceKey_background, Converter={StaticResource _resourceLookupConverter}}"
Foreground="{Binding _ResourceKey_foreground, Converter={StaticResource _resourceLookupConverter}}"
FontFamily="{Binding _ResourceKey_fontFamily, Converter={StaticResource _resourceLookupConverter}}"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Code behind:
public class _2ResourceLookupConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return App.Current.TryFindResource(value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Binding.DoNothing;
}
}
Here are the 2 classes for the user defined paragraph styles:
public class _2StylesPara : ObservableCollection<_2StylePara>
// ObservableCollection implements INotifyPropertyChanged
{
public _2StylesPara(){}
}
public class _2StylePara
{
public event PropertyChangedEventHandler PropertyChanged;
// This method is not reached if Background, Foreground or FontFamily changes
private void SetValue<T>(ref T property, T value, string propertyName = null)
{
if (object.Equals(property, value) == false)
{
property = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
private string _nameInternal = string.Empty;
private string _nameUI = string.Empty;
private string _resourceKey_background = string.Empty;
private string _resourceKey_foreground = string.Empty;
private string _resourceKey_fontFamily = string.Empty;
private string _resourceKey_nameUI = string.Empty;
private string _resourceKey_style = string.Empty;
private Style _style = null;
private ResourceDictionary _valuesRD = null;
private string _pathToValuesRD = string.Empty;
public string NameInternal
{
get { return this._nameInternal; }
set { SetValue(ref this._nameInternal, value); }
}
public string NameUI
{
get { return this._nameUI; }
set { SetValue(ref this._nameUI, value); }
}
public string ResourceKey_background
{
get { return this._resourceKey_background; }
set { SetValue(ref this._resourceKey_background, value); }
}
public string ResourceKey_foreground
{
get { return this._resourceKey_foreground; }
set { SetValue(ref this._resourceKey_foreground, value); }
}
public string ResourceKey_fontFamily
{
get { return this._resourceKey_fontFamily; }
set { SetValue(ref this._resourceKey_fontFamily, value); }
}
public string ResourceKey_nameUI
{
get { return this._resourceKey_nameUI; }
set { SetValue(ref this._resourceKey_nameUI, value); }
}
public string ResourceKey_style
{
get { return this._resourceKey_style; }
set { SetValue(ref this._resourceKey_style, value); }
}
public Style Style
{
get { return this._style; }
set { SetValue(ref this._style, value); }
}
public ResourceDictionary ValuesRD
{
get { return this._valuesRD; }
set { SetValue(ref this._valuesRD, value); }
}
public string PathToValuesRD
{
get { return this._pathToValuesRD; }
set { SetValue(ref this._pathToValuesRD, value); }
}
// Constructor
public _2StylePara(Style sty, string styleNameInternal, string styleNameUI, string resourceKey_style, string resourceKey_nameUI,
string resourceKey_foreground, string resourceKey_background, string resourceKey_fontFamily,
ResourceDictionary valuesRD, string pathToValuesRD)
{
_style = sty;
_nameInternal = styleNameInternal; // [ "_sty001" ]
_nameUI = styleNameUI; // [ "Standard" ]
_resourceKey_style = resourceKey_style; // [ "_stylePara001" ]
_resourceKey_nameUI = resourceKey_nameUI; // [ "_nameUi001 ]
_resourceKey_foreground = resourceKey_foreground; // [ "_brush_textcolor001" ]
_resourceKey_background = resourceKey_background; // [ "_brush_backcolor001" ]
_resourceKey_fontFamily = resourceKey_fontFamily; // [ "_fontFamily001" ]
_valuesRD = valuesRD; // This ResourceDictionary contains all style values
_pathToValuesRD = pathToValuesRD; // [ "...\Resources\1ParaStyleValuesRD001.xaml" ]
}
}