Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.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# ListBox数据模板中的属性绑定不正确_C#_Wpf_Data Binding_Mvvm_Mvvm Light - Fatal编程技术网

C# ListBox数据模板中的属性绑定不正确

C# ListBox数据模板中的属性绑定不正确,c#,wpf,data-binding,mvvm,mvvm-light,C#,Wpf,Data Binding,Mvvm,Mvvm Light,我在让列表框正确绑定到集合时遇到了一些问题 public Foo() { Bars = new ObservableCollection<string>(); ... } 我将给出框架代码,然后解释我希望它做什么 XAML标记: <ListBox DataContext="{Binding Foos, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Items

我在让列表框正确绑定到集合时遇到了一些问题

public Foo()
{
    Bars = new ObservableCollection<string>();
    ...
}
我将给出框架代码,然后解释我希望它做什么

XAML标记:

<ListBox DataContext="{Binding Foos, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                       ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" 
                       SelectedItem="{Binding Main.SelectedFoo, Mode=TwoWay, 
                       Source={StaticResource Locator}, 
                       UpdateSourceTrigger=PropertyChanged}" 
                       SelectedValue="{Binding Main.SelectedFoo, Source={StaticResource Locator}}"/>


<ListBox ItemsSource="{Binding Main.SelectedFoo.Bars}"  SelectedItem="{Binding Main.SelectedBar}"  >
<ListBox.ItemTemplate>
    <DataTemplate>
        <Grid HorizontalAlignment="Right">
            <!-- The binding requires "{Binding .}" because a path must be explicitly set for Two-Way binding,
                 even though {Binding .} is supposed to be identical to {Binding} -->
                <TextBox Text="{Binding Path=. , UpdateSourceTrigger=PropertyChanged}"  />
         </Grid>
    </DataTemplate>
</ListBox.ItemTemplate>
private ObservableCollection<Foo> _barList = new ObservableCollection<Foo>();
private const string BardListPN = "FooList";

public ObservableCollection<Foo> FooList
{
    get { return _fooList; }

    set
    {
        if (_fooList == value)
        {
            return;
        }

        var oldValue = _fooList;
        _fooList = value;

        RaisePropertyChanged(FooListPN);
    }
}

private Foo _selectedFoo;
private const string SelectedFooPN = "SelectedFoo";

public Foo SelectedFoo
{
    get { return _selectedFoo; }

    set
    {
        if (_selectedFoo == value)
        {
            return;
        }

        var oldValue = _selectedFoo;
        _selectedFoo = value;

        // Update bindings, no broadcast
        RaisePropertyChanged(SelectedFooPN);
    }
}

public const string SelectedBarPN = "SelectedBar";
private string _selectedBar = "";

public string SelectedBar
{
    get
    {
        return _selectedBar;
    }

    set
    {
        if (_selectedBar == value)
        {
            return;
        }

        var oldValue = _selectedBar;
        _selectedBar = value;


        // Update bindings, no broadcast
        RaisePropertyChanged(SelectedBarPN);
    }
}
public class Foo
{
    public ICollection<string> Bars
    {
        get { return _bars; }
        set
        {
            _bars= value;
            NotifyPropertyChanged("Bars"); 
            // snipped obvious INotifyPropertyChanged boilerplate code
        }
    }
}

C#视图模型:

<ListBox DataContext="{Binding Foos, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                       ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" 
                       SelectedItem="{Binding Main.SelectedFoo, Mode=TwoWay, 
                       Source={StaticResource Locator}, 
                       UpdateSourceTrigger=PropertyChanged}" 
                       SelectedValue="{Binding Main.SelectedFoo, Source={StaticResource Locator}}"/>


<ListBox ItemsSource="{Binding Main.SelectedFoo.Bars}"  SelectedItem="{Binding Main.SelectedBar}"  >
<ListBox.ItemTemplate>
    <DataTemplate>
        <Grid HorizontalAlignment="Right">
            <!-- The binding requires "{Binding .}" because a path must be explicitly set for Two-Way binding,
                 even though {Binding .} is supposed to be identical to {Binding} -->
                <TextBox Text="{Binding Path=. , UpdateSourceTrigger=PropertyChanged}"  />
         </Grid>
    </DataTemplate>
</ListBox.ItemTemplate>
private ObservableCollection<Foo> _barList = new ObservableCollection<Foo>();
private const string BardListPN = "FooList";

public ObservableCollection<Foo> FooList
{
    get { return _fooList; }

    set
    {
        if (_fooList == value)
        {
            return;
        }

        var oldValue = _fooList;
        _fooList = value;

        RaisePropertyChanged(FooListPN);
    }
}

private Foo _selectedFoo;
private const string SelectedFooPN = "SelectedFoo";

public Foo SelectedFoo
{
    get { return _selectedFoo; }

    set
    {
        if (_selectedFoo == value)
        {
            return;
        }

        var oldValue = _selectedFoo;
        _selectedFoo = value;

        // Update bindings, no broadcast
        RaisePropertyChanged(SelectedFooPN);
    }
}

public const string SelectedBarPN = "SelectedBar";
private string _selectedBar = "";

public string SelectedBar
{
    get
    {
        return _selectedBar;
    }

    set
    {
        if (_selectedBar == value)
        {
            return;
        }

        var oldValue = _selectedBar;
        _selectedBar = value;


        // Update bindings, no broadcast
        RaisePropertyChanged(SelectedBarPN);
    }
}
public class Foo
{
    public ICollection<string> Bars
    {
        get { return _bars; }
        set
        {
            _bars= value;
            NotifyPropertyChanged("Bars"); 
            // snipped obvious INotifyPropertyChanged boilerplate code
        }
    }
}
private observedcollection\u barList=new observedcollection();
私有常量字符串BardListPN=“傻瓜”;
公众观察收集愚人
{
获取{return}
设置
{
如果(_傻瓜==值)
{
返回;
}
var oldValue=\u傻瓜;
_愚人=价值;
RaisePropertyChanged(愚人党);
}
}
私人食品(选择食品);;
私有常量字符串SelectedFooPN=“SelectedFoo”;
公共食物选择食物
{
获取{return\u selectedFoo;}
设置
{
如果(_selectedFoo==值)
{
返回;
}
var oldValue=_selectedFoo;
_selectedFoo=值;
//更新绑定,无广播
RaisePropertyChanged(已选择Foopn);
}
}
public const string SelectedBarPN=“SelectedBar”;
私有字符串_selectedBar=“”;
公共字符串选择栏
{
得到
{
返回_selectedBar;
}
设置
{
如果(_selectedBar==值)
{
返回;
}
var oldValue=_selectedBar;
_selectedBar=值;
//更新绑定,无广播
RaisePropertyChanged(已选择BARPN);
}
}
C#型号:

<ListBox DataContext="{Binding Foos, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                       ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" 
                       SelectedItem="{Binding Main.SelectedFoo, Mode=TwoWay, 
                       Source={StaticResource Locator}, 
                       UpdateSourceTrigger=PropertyChanged}" 
                       SelectedValue="{Binding Main.SelectedFoo, Source={StaticResource Locator}}"/>


<ListBox ItemsSource="{Binding Main.SelectedFoo.Bars}"  SelectedItem="{Binding Main.SelectedBar}"  >
<ListBox.ItemTemplate>
    <DataTemplate>
        <Grid HorizontalAlignment="Right">
            <!-- The binding requires "{Binding .}" because a path must be explicitly set for Two-Way binding,
                 even though {Binding .} is supposed to be identical to {Binding} -->
                <TextBox Text="{Binding Path=. , UpdateSourceTrigger=PropertyChanged}"  />
         </Grid>
    </DataTemplate>
</ListBox.ItemTemplate>
private ObservableCollection<Foo> _barList = new ObservableCollection<Foo>();
private const string BardListPN = "FooList";

public ObservableCollection<Foo> FooList
{
    get { return _fooList; }

    set
    {
        if (_fooList == value)
        {
            return;
        }

        var oldValue = _fooList;
        _fooList = value;

        RaisePropertyChanged(FooListPN);
    }
}

private Foo _selectedFoo;
private const string SelectedFooPN = "SelectedFoo";

public Foo SelectedFoo
{
    get { return _selectedFoo; }

    set
    {
        if (_selectedFoo == value)
        {
            return;
        }

        var oldValue = _selectedFoo;
        _selectedFoo = value;

        // Update bindings, no broadcast
        RaisePropertyChanged(SelectedFooPN);
    }
}

public const string SelectedBarPN = "SelectedBar";
private string _selectedBar = "";

public string SelectedBar
{
    get
    {
        return _selectedBar;
    }

    set
    {
        if (_selectedBar == value)
        {
            return;
        }

        var oldValue = _selectedBar;
        _selectedBar = value;


        // Update bindings, no broadcast
        RaisePropertyChanged(SelectedBarPN);
    }
}
public class Foo
{
    public ICollection<string> Bars
    {
        get { return _bars; }
        set
        {
            _bars= value;
            NotifyPropertyChanged("Bars"); 
            // snipped obvious INotifyPropertyChanged boilerplate code
        }
    }
}
公共类Foo
{
公共ICollection酒吧
{
获取{返回_条;}
设置
{
_条=值;
NotifyPropertyChanged(“酒吧”);
//剪下明显的InotifyProperty更改样板代码
}
}
}
我的问题是,
Bar
集合中字符串的文本框没有设置任何更改。当选定的
Foo
更改为不同的
Foo
并返回时,将显示原始的

有人能告诉我我做错了什么吗?这看起来应该简单得多。谢谢


更新:我已经按照Tri Q的建议更改了代码,但是对文本框所做的更改并没有反映在属性本身中。有什么想法吗?

在这个例子中,我采用的Foo模型类已经简化,但是省略的代码可能是问题的罪魁祸首。让我解释一下

Foo还需要实现INotifyPropertyChanged,以便让Listbox知道何时初始化了Bars集合,这完全取决于何时初始化它

假设您在Foo的构造函数中初始化了Bars,则会导致Listbox ItemsSource绑定到有效的Bars集合

public Foo()
{
    Bars = new ObservableCollection<string>();
    ...
}
其次,为
itemsource
设置
Mode=“TwoWay”
没有意义。ItemsSource=“{Binding Main.SelectedFoo.bar,Mode=TwoWay}”


最后,您不需要为
数据模板
设置
数据类型
。DataType=“{x:Type System:String}”

真棒的答案!非常感谢你提供的额外信息。是的,正如您可以清楚地看到的,我仍在学习WPF和MVVM,我真诚地感谢您的评论。我会试试你的建议。有一点需要注意:我绑定
文本框的方式是,需要一个路径,因为模式是
TwoWay
(默认情况下也是如此),我在XAML注释中注意到了这一点。这似乎是将
文本框
绑定到集合中当前项的唯一方法。