Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将ObservableCollection的所有元素绑定到TextBlock_C#_Wpf_Binding_Observablecollection_Textblock - Fatal编程技术网

C# 将ObservableCollection的所有元素绑定到TextBlock

C# 将ObservableCollection的所有元素绑定到TextBlock,c#,wpf,binding,observablecollection,textblock,C#,Wpf,Binding,Observablecollection,Textblock,我正在尝试将TextBlock绑定到ObservableCollection中的项。TextBlock值应最多生成集合中的元素。集合中的元素计数介于0和7之间(如果有帮助)。MyClass实现了INotifyPropertyChanged。它应该直接是TextBlock,而不是ListBox。我怎么做?谢谢 更新:问题是我以前不知道集合中的元素数。我知道在这种情况下最好使用ListBox或ListView,但在TextBlock或Label中使用它很重要 例如: 1.ObservableC

我正在尝试将TextBlock绑定到ObservableCollection中的项。TextBlock值应最多生成集合中的元素。集合中的元素计数介于0和7之间(如果有帮助)。MyClass实现了INotifyPropertyChanged。它应该直接是TextBlock,而不是ListBox。我怎么做?谢谢
更新:问题是我以前不知道集合中的元素数。我知道在这种情况下最好使用ListBox或ListView,但在TextBlock或Label中使用它很重要

例如:
1.ObservableCollection包含元素0、1、2。
文本块应包含以下“值:0、1、2”
2.ObservableCollection包含元素0、1。
文本块应包含以下“值:0,1”



ObservableCollection值=新的ObservableCollection();
公共可观测收集值
{
get=>值;
设置
{
价值=价值;
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();
    }
}
公共类StringsCollectionConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
if(value==null)返回null;
返回字符串.Join(“\n”,值为ObservableCollection);
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
抛出新的NotImplementedException();
}
}
Xaml

<Window.Resources>
    <local:StringsCollectionConverter x:Key="StringsCollectionConverter"/>
</Window.Resources> 
<Grid>
    <TextBlock Text="{Binding TextBlockCollection, Converter={StaticResource StringsCollectionConverter}}"></TextBlock>
</Grid>

您必须使用转换器绑定到集合。
问题是在集合更改时更新值(这里我的意思是不为新集合设置值,而是向集合添加/从集合中删除项)。
要在添加/删除时实现更新,您必须将
多重绑定
与ObservaleCollection.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.");
    }
}

公共类多值转换器:IMultiValueConverter
{
公共对象转换(对象[]值,类型targetType,对象参数,CultureInfo区域性)
{
如果(values.Length>1&&values[0]为ICollection mycl)
{
var retVal=string.Empty;
var firstelem=真;
foreach(mycl中的变量项)
{
retVal+=$“{(firstelem?string.Empty:”,“”}{item}”;
firstelem=假;
}
返回返回;
}
其他的
不做任何事;
}
公共对象[]转换回(对象值,类型[]目标类型,对象参数,CultureInfo区域性)
{
抛出新的NotImplementedException(“这是一个单向转换器”);
}
}

创建一个附加字符串属性,该属性将在每次集合项更改时更改:

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);}
    }
}
公共类虚拟机
{
公共虚拟机()
{ 
//通过属性分配的新集合,因为属性setter添加了事件处理程序
值=新的ObservableCollection();
}
可观察收集值;
公共可观测收集值
{
get=>值;
设置
{
if(values!=null)values.CollectionChanged-=CollectionChangedHandler;
价值=价值;
if(values!=null)values.CollectionChanged+=CollectionChangedHandler;
OnPropertyChanged();
}
}
私有void CollectionChangedHandler(对象发送方,NotifyCollectionChangedEventArgs e)
{
关于财产变更(“价值文本”);
}
公共字符串值文本
{
获取{return”值:“+String.Join(“,”,值);}
}
}
然后绑定到该属性:

<TextBlock Text="{Binding ValuesText}"/>


可能重复@MikeT,我不认为这是重复提供的链接。问题是如何绑定ObservableCollection中的多个条目,而不是集合中单个条目中的多个值。问题是,如果集合发生更改,文本将不会更新。是的,请确保使用双向绑定,实现INotifyPropertyChanged接口并调用OnPropertyChanged(“TextBlockCollection”);收藏更改后,我的意思是,如果同一个收藏有一个以上的项目。我没有遵循?你是对的!我道歉!我撤销了我的否决票(但你可能需要改变你的答案,因为它是有效的),这里绝对不需要多重绑定!使用多重绑定,我不需要在每次集合修改时在VewModel(No NotifyPropertyChanged)中执行某些操作。您没有使用值[1],为什么要传递它呢!对于
MultiBinding
而言,如果
Count
发生更改,则会更新目标。这绝对是处理ViewModel中所有内容的一个选项。问题是它最好属于哪里(视图还是视图模型)?@Rekshino,VM。例如,有一个完整的ReactiveUI框架,它使用这样的属性left和right:see,
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}"/>