通过转换器绑定到 ObservableCollection 的文本字符串未在集合更改时更新
Text string bound to an ObservableCollection through a Converter not updating on collection change
我有一个非常简单的 IValueConverter,可以将 IList<string>
转换为逗号分隔的字符串。问题是集合(它是一个 ObservableCollection)没有尝试更新文本,我可以说是因为 IValueConverter 中的调试点显示在加载初始绑定后没有调用它。
转换器(这部分在实际调用时似乎工作正常)
public class CollectionToCommaSeperatedString : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return parameter.ToString();
if (((IList<string>)value).Count > 0)
return String.Join(", ", ((IList<string>)value).ToArray()) ?? parameter.ToString();
else
return parameter.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
绑定元素:
<TextBlock Text="{Binding SelectedChannels, ConverterParameter='(Click to select channels)', Converter={StaticResource CollectionToCommaSeperatedString}, ElementName=userControl, Mode=OneWay}" HorizontalAlignment="Left" VerticalAlignment="Top"/>
属性 的 CB:
public ObservableCollection<string> SelectedChannels
{
get { return (ObservableCollection<string>)GetValue(SelectedChannelsProperty); }
set { SetValue(SelectedChannelsProperty, value); }
}
public static readonly DependencyProperty SelectedChannelsProperty =
DependencyProperty.Register("SelectedChannels", typeof(ObservableCollection<string>), typeof(ChannelSelector), new PropertyMetadata(new ObservableCollection<string>()));
实现所需的一种可能性是将转换器逻辑包装到可重用行为中。
这是一个,它会像您的转换器一样工作,但只适用于 TextBlock.Text
:
public static class Behaviors
{
public static ObservableCollection<string> GetTest(DependencyObject obj) => (ObservableCollection<string>)obj.GetValue(TestProperty);
public static void SetTest(DependencyObject obj, ObservableCollection<string> value) => obj.SetValue(TestProperty, value);
public static readonly DependencyProperty TestProperty =
DependencyProperty.RegisterAttached("Test", typeof(ObservableCollection<string>), typeof(Behaviors), new PropertyMetadata(null, (d, e) =>
{
var textBlock = d as TextBlock;
var collection = e.NewValue as ObservableCollection<string>;
collection.CollectionChanged += (s, a) =>
{
// put logic here
textBlock.Text = ... ;
};
}));
}
这样使用:
<TextBlock local:Behaviors.Test="{Binding ...}" />
TODO:添加空检查、取消订阅(如果绑定到持久的 ViewModel 属性可能会导致内存泄漏)、正确命名...
我有一个非常简单的 IValueConverter,可以将 IList<string>
转换为逗号分隔的字符串。问题是集合(它是一个 ObservableCollection)没有尝试更新文本,我可以说是因为 IValueConverter 中的调试点显示在加载初始绑定后没有调用它。
转换器(这部分在实际调用时似乎工作正常)
public class CollectionToCommaSeperatedString : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return parameter.ToString();
if (((IList<string>)value).Count > 0)
return String.Join(", ", ((IList<string>)value).ToArray()) ?? parameter.ToString();
else
return parameter.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
绑定元素:
<TextBlock Text="{Binding SelectedChannels, ConverterParameter='(Click to select channels)', Converter={StaticResource CollectionToCommaSeperatedString}, ElementName=userControl, Mode=OneWay}" HorizontalAlignment="Left" VerticalAlignment="Top"/>
属性 的 CB:
public ObservableCollection<string> SelectedChannels
{
get { return (ObservableCollection<string>)GetValue(SelectedChannelsProperty); }
set { SetValue(SelectedChannelsProperty, value); }
}
public static readonly DependencyProperty SelectedChannelsProperty =
DependencyProperty.Register("SelectedChannels", typeof(ObservableCollection<string>), typeof(ChannelSelector), new PropertyMetadata(new ObservableCollection<string>()));
实现所需的一种可能性是将转换器逻辑包装到可重用行为中。
这是一个,它会像您的转换器一样工作,但只适用于 TextBlock.Text
:
public static class Behaviors
{
public static ObservableCollection<string> GetTest(DependencyObject obj) => (ObservableCollection<string>)obj.GetValue(TestProperty);
public static void SetTest(DependencyObject obj, ObservableCollection<string> value) => obj.SetValue(TestProperty, value);
public static readonly DependencyProperty TestProperty =
DependencyProperty.RegisterAttached("Test", typeof(ObservableCollection<string>), typeof(Behaviors), new PropertyMetadata(null, (d, e) =>
{
var textBlock = d as TextBlock;
var collection = e.NewValue as ObservableCollection<string>;
collection.CollectionChanged += (s, a) =>
{
// put logic here
textBlock.Text = ... ;
};
}));
}
这样使用:
<TextBlock local:Behaviors.Test="{Binding ...}" />
TODO:添加空检查、取消订阅(如果绑定到持久的 ViewModel 属性可能会导致内存泄漏)、正确命名...