将 ObservableCollection 的所有元素绑定到 TextBlock
Binding all elements of ObservableCollection to TextBlock
我正在尝试将 TextBlock 绑定到 ObservableCollection 中的项目。 TextBlock 值应该生成到集合中的元素。集合中元素的数量在 0 到 7 之间(如果有帮助的话)。 MyClass 实现了 INotifyPropertyChanged。应该直接是TextBlock,而不是ListBox。我该怎么做?谢谢!
Update:The 问题是我以前不知道集合中元素的数量。我知道在这种情况下最好使用 ListBox 或 ListView,但在 TextBlock 或 Label 中制作它很重要
例如:
1.ObservableCollection 包含元素 0、1、2。
TextBlock 应包含以下 "Values: 0, 1, 2"
2. ObservableCollection 包含元素 0, 1.
TextBlock 应包含以下 "Values: 0, 1"
<TextBlock>
<Run Text="Values: "/>
<Run Text="{Binding Values}" />
</TextBlock>
ObservableCollection<int> values = new ObservableCollection<int>();
public ObservableCollection<int> Values
{
get => values;
set
{
values = value;
OnPropertyChanged();
}
}
使用连接这些字符串的转换器:
public class StringsCollectionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
return string.Join("\n", value as ObservableCollection<string>);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Xaml
<Window.Resources>
<local:StringsCollectionConverter x:Key="StringsCollectionConverter"/>
</Window.Resources>
<Grid>
<TextBlock Text="{Binding TextBlockCollection, Converter={StaticResource StringsCollectionConverter}}"></TextBlock>
</Grid>
您必须使用转换器绑定到集合。
问题是在集合更改时更新值(这里我的意思是不将值设置为新集合,而是 adding/removing 项目 to/from 集合)。
要在 add/remove 上实现更新,您必须将 MultiBinding
与 ObservableCollection.Count 的绑定之一一起使用,因此如果更改计数,则绑定 属性 将被更新。
<Window.Resources>
<local:MultValConverter x:Key="multivalcnv"/>
</Window.Resources>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource multivalcnv}">
<Binding Path="Values"/>
<Binding Path="Values.Count"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
public class MultValConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length > 1 && values[0] is ICollection myCol)
{
var retVal = string.Empty;
var firstelem = true;
foreach (var item in myCol)
{
retVal += $"{(firstelem?string.Empty:", ")}{item}";
firstelem = false;
}
return retVal;
}
else
return Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException("It's a one way converter.");
}
}
创建一个额外的字符串属性,每次收集项[s]改变时它都会改变:
public class Vm
{
public Vm()
{
// new collection assigned via property because property setter adds event handler
Values = new ObservableCollection<int>();
}
ObservableCollection<int> values;
public ObservableCollection<int> Values
{
get => values;
set
{
if (values != null) values.CollectionChanged -= CollectionChangedHandler;
values = value;
if (values != null) values.CollectionChanged += CollectionChangedHandler;
OnPropertyChanged();
}
}
private void CollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged("ValuesText");
}
public string ValuesText
{
get { return "Values: " + String.Join(", ", values);}
}
}
然后绑定到 属性:
<TextBlock Text="{Binding ValuesText}"/>
我正在尝试将 TextBlock 绑定到 ObservableCollection 中的项目。 TextBlock 值应该生成到集合中的元素。集合中元素的数量在 0 到 7 之间(如果有帮助的话)。 MyClass 实现了 INotifyPropertyChanged。应该直接是TextBlock,而不是ListBox。我该怎么做?谢谢!
Update:The 问题是我以前不知道集合中元素的数量。我知道在这种情况下最好使用 ListBox 或 ListView,但在 TextBlock 或 Label 中制作它很重要
例如:
1.ObservableCollection 包含元素 0、1、2。
TextBlock 应包含以下 "Values: 0, 1, 2"
2. ObservableCollection 包含元素 0, 1.
TextBlock 应包含以下 "Values: 0, 1"
<TextBlock>
<Run Text="Values: "/>
<Run Text="{Binding Values}" />
</TextBlock>
ObservableCollection<int> values = new ObservableCollection<int>();
public ObservableCollection<int> Values
{
get => values;
set
{
values = value;
OnPropertyChanged();
}
}
使用连接这些字符串的转换器:
public class StringsCollectionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
return string.Join("\n", value as ObservableCollection<string>);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Xaml
<Window.Resources>
<local:StringsCollectionConverter x:Key="StringsCollectionConverter"/>
</Window.Resources>
<Grid>
<TextBlock Text="{Binding TextBlockCollection, Converter={StaticResource StringsCollectionConverter}}"></TextBlock>
</Grid>
您必须使用转换器绑定到集合。
问题是在集合更改时更新值(这里我的意思是不将值设置为新集合,而是 adding/removing 项目 to/from 集合)。
要在 add/remove 上实现更新,您必须将 MultiBinding
与 ObservableCollection.Count 的绑定之一一起使用,因此如果更改计数,则绑定 属性 将被更新。
<Window.Resources>
<local:MultValConverter x:Key="multivalcnv"/>
</Window.Resources>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource multivalcnv}">
<Binding Path="Values"/>
<Binding Path="Values.Count"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
public class MultValConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Length > 1 && values[0] is ICollection myCol)
{
var retVal = string.Empty;
var firstelem = true;
foreach (var item in myCol)
{
retVal += $"{(firstelem?string.Empty:", ")}{item}";
firstelem = false;
}
return retVal;
}
else
return Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException("It's a one way converter.");
}
}
创建一个额外的字符串属性,每次收集项[s]改变时它都会改变:
public class Vm
{
public Vm()
{
// new collection assigned via property because property setter adds event handler
Values = new ObservableCollection<int>();
}
ObservableCollection<int> values;
public ObservableCollection<int> Values
{
get => values;
set
{
if (values != null) values.CollectionChanged -= CollectionChangedHandler;
values = value;
if (values != null) values.CollectionChanged += CollectionChangedHandler;
OnPropertyChanged();
}
}
private void CollectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged("ValuesText");
}
public string ValuesText
{
get { return "Values: " + String.Join(", ", values);}
}
}
然后绑定到 属性:
<TextBlock Text="{Binding ValuesText}"/>