C#WPF-类的数据绑定可观察集合的组合框

C#WPF-类的数据绑定可观察集合的组合框,c#,.net,wpf,data-binding,combobox,C#,.net,Wpf,Data Binding,Combobox,最近,我开始将一个概念验证UWP应用程序转换为一个工作WPF应用程序 我想要的是有两个下拉列表(组合框)的“字符”,我可以选择,我希望他们数据绑定到一个ObservableCollection属性,其中我选择的字符存储在一个不同的字符属性的球员1然后球员2 我在UWP应用程序中使用了下拉菜单数据绑定,但在WPF应用程序中无法使用 在WPF应用程序中,组合框保持为空,我无法选择选项 我试着按照这个问题的答案来回答,但我想我遗漏了一些东西: 以下是代码,保持最小值: 字符.cs public cla

最近,我开始将一个概念验证UWP应用程序转换为一个工作WPF应用程序

我想要的是有两个下拉列表(组合框)的“字符”,我可以选择,我希望他们数据绑定到一个ObservableCollection属性,其中我选择的字符存储在一个不同的字符属性的球员1然后球员2

我在UWP应用程序中使用了下拉菜单数据绑定,但在WPF应用程序中无法使用

在WPF应用程序中,组合框保持为空,我无法选择选项

我试着按照这个问题的答案来回答,但我想我遗漏了一些东西:

以下是代码,保持最小值:

字符.cs

public class Character : INotifyPropertyChanged
{
    private int _id;
    public int Id
    {
        get
        {
            return _id;
        }
        set
        {
            _id = value;
        }
    }

    private string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public Character(int id, string name)
    {
        Id = id;
        Name = name;
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
public partial class MainWindow : Window, INotifyPropertyChanged
{
    private ObservableCollection<Character> _characterList;
    public ObservableCollection<Character> CharacterList
    {
        get
        {
            return _characterList;
        }
        set
        {
            _characterList = value;
        }
    }

    private Character _player1SelectedCharacter;
    public Character Player1SelectedCharacter
    {
        get
        {
            return _player1SelectedCharacter;
        }
        set
        {
            _player1SelectedCharacter = value;
        }
    }

    private Character _player2SelectedCharacter;
    public Character Player2SelectedCharacter
    {
        get
        {
            return _player2SelectedCharacter;
        }
        set
        {
            _player2SelectedCharacter = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public MainWindow()
    {
        this.DataContext = this;
        InitializeComponent();
        CharacterList = new ObservableCollection<Character>
        {
            new Character(0, "Mario"),
            new Character(1, "Luigi"),
            new Character(2, "Wario"),
        };
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
main window.xaml

<Window x:Class="SmashWiiUOverlayManager.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SmashWiiUOverlayManager"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>

        <StackPanel Grid.Column="0" Grid.Row="0">
            <ComboBox 
                Name="Player1CharacterDropdown" 
                ItemsSource="{Binding CharacterList, Mode=TwoWay}" 
                SelectedItem="{Binding Player1SelectedCharacter, Mode=TwoWay}" 
                SelectedValuePath="Name" 
                DisplayMemberPath="Name"
                Width="144">
            </ComboBox>
        </StackPanel>

        <StackPanel Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right">
            <ComboBox 
                Name="Player2CharacterDropdown" 
                ItemsSource="{Binding CharacterList, Mode=TwoWay}" 
                SelectedItem="{Binding Player2SelectedCharacter, Mode=TwoWay}" 
                SelectedValuePath="Character" 
                DisplayMemberPath="Name"
                Width="144">
            </ComboBox>
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.cs

public class Character : INotifyPropertyChanged
{
    private int _id;
    public int Id
    {
        get
        {
            return _id;
        }
        set
        {
            _id = value;
        }
    }

    private string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public Character(int id, string name)
    {
        Id = id;
        Name = name;
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
public partial class MainWindow : Window, INotifyPropertyChanged
{
    private ObservableCollection<Character> _characterList;
    public ObservableCollection<Character> CharacterList
    {
        get
        {
            return _characterList;
        }
        set
        {
            _characterList = value;
        }
    }

    private Character _player1SelectedCharacter;
    public Character Player1SelectedCharacter
    {
        get
        {
            return _player1SelectedCharacter;
        }
        set
        {
            _player1SelectedCharacter = value;
        }
    }

    private Character _player2SelectedCharacter;
    public Character Player2SelectedCharacter
    {
        get
        {
            return _player2SelectedCharacter;
        }
        set
        {
            _player2SelectedCharacter = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public MainWindow()
    {
        this.DataContext = this;
        InitializeComponent();
        CharacterList = new ObservableCollection<Character>
        {
            new Character(0, "Mario"),
            new Character(1, "Luigi"),
            new Character(2, "Wario"),
        };
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
public分部类主窗口:窗口,INotifyPropertyChanged
{
私有可观察集合\u字符列表;
公共可见集合字符列表
{
得到
{
返回字符列表;
}
设置
{
_characterList=值;
}
}
私人角色(玩家1选择角色),;
公共角色扮演者1选定角色
{
得到
{
返回\u player1所选字符;
}
设置
{
_player1SelectedCharacter=值;
}
}
私人角色_player2选择角色;
公共角色扮演者2选择角色
{
得到
{
返回_player2所选字符;
}
设置
{
_player2SelectedCharacter=值;
}
}
公共事件PropertyChangedEventHandler PropertyChanged=委托{};
公共主窗口()
{
this.DataContext=this;
初始化组件();
CharacterList=新的ObservableCollection
{
新字符(0,“马里奥”),
新字符(1,“Luigi”),
新角色(2,“瓦里奥”),
};
}
public void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
this.PropertyChanged(this,newpropertychangedventargs(propertyName));
}
}
此代码当前将组合框保留为空

当我使用:

Player1CharacterDropdown.ItemsSource = new ObservableCollection<Character>
{
    new Character(0, "Mario", ".\\images\\mario.png"),
    new Character(1, "Luigi", ".\\images\\luigi.png"),
    new Character(2, "Wario", ".\\images\\wario.png"),
};
Player1CharacterDropdown.ItemsSource=新的ObservableCollection
{
新字符(0,“Mario”,“\\images\\Mario.png”),
新字符(1,“Luigi”,“\\images\\Luigi.png”),
新字符(2,“Wario”,“\\images\\Wario.png”),
};
。。。combox被填充,但它是数据绑定到属性的,这正是我想要的


我在这里遗漏了什么?

这可能与此问题有关,也可能与此问题无关,但它很重要:
This.PropertyChanged(This,new-PropertyChangedEventArgs(propertyName))
:如果没有人订阅
PropertyChanged
,您预计会发生什么情况?您是对的,没有订阅任何内容,我只是将所有属性绑定到它,应用程序现在可以执行我想要的操作。这里的问题是
CharacterList
只有在您设置
this.DataContext=this。没有通知。当
CharacterList
最终初始化时,绑定不会更新目标,因为您不会告诉它需要更新。如果在设置DataContext之前初始化
CharacterList
,则在您期望另一个非通知属性(例如
Player1SelectedCharacter
)引发通知事件之前,一切正常。创建具有所有这些属性的主视图模型。不要尝试这样做。我听从了你的建议,我现在使用的是ViewModel,所有内容现在都设置在datacontext之前,并且所有内容都订阅了OnPropertyChanged。非常感谢。