2017-05-29 111 views
-1

我是WPF新手,所以我必须缺少一些非常明显的东西。WPF绑定组合框选择项目到列表查看当前项目

我有这个简单的设置:

public partial class MainWindow : Window 
{ 
    public ObservableCollection<Student> Students { get; set; } 
    public ObservableCollection<Student> ClassroomStudents { get; set; } 

    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this; 

     Students = new ObservableCollection<Student>(); 

     Students.Add(new Student { ID = 1, Name = "John" }); 
     Students.Add(new Student { ID = 2, Name = "Paul" }); 
     Students.Add(new Student { ID = 3, Name = "Ringo"}); 
     Students.Add(new Student { ID = 4, Name = "George" }); 

     ClassroomStudents = new ObservableCollection<Student>(); 
     ClassroomStudents.Add(Students[0]); //View binds it ok at startup (one way) 
     ClassroomStudents.Add(Students[1]); //View binds ut ok at startup (one way) 

    } 


    public class Student : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     public int ID { get; set; } 
     public string Name { get; set; } 
    } 

    private void bOK_Click(object sender, RoutedEventArgs e) 
    { 
     MessageBox.Show(ClassroomStudents[0].Name); 

} 

我想实现的是显示ClassroomStudents收集和应对其绑定到集合项目的每个项目添加一个组合框。

<Grid> 
    <ListView x:Name="SortBy" ItemsSource="{Binding ClassroomStudents}" Grid.Column="0"> 
     <ListView.View> 
      <GridView> 
       <GridViewColumn Header="Name" Width="80"> 
        <GridViewColumn.CellTemplate> 
         <DataTemplate>        
          <ComboBox          
           ItemsSource="{Binding Students, RelativeSource={ RelativeSource AncestorType=Window}}" 
           DisplayMemberPath="Name"           
           SelectedItem="{Binding Path=.,Mode=TwoWay}"                   
           > 
          </ComboBox> 
          <!--<Label Content="{Binding}"></Label>--> 
         </DataTemplate> 
        </GridViewColumn.CellTemplate> 
       </GridViewColumn>     
      </GridView> 
     </ListView.View> 
    </ListView> 

    <!--OK/CANCEL BUTTONS--> 
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="1" Margin="0,10,0,0"> 
     <Button x:Name="bOK" IsDefault="True" Margin="10" Width="100" Click="bOK_Click">OK</Button> 
     <Button x:Name="bCancel" IsCancel="True" Margin="10" Grid.Column="1" Width="100" Click="bCancel_Click">Cancel</Button> 
    </StackPanel> 
</Grid> 

它结合精细的一种方法:如果我选择在组合框中另一名学生

image

但是该模型收藏价值不会改变:

MessageBox.Show(ClassroomStudents[0].Name); //Always return John 

我发现一些答案建议绑定到一个属性(即ID),但我想绑定到集合Item(Student)。

谢谢, Rodo。

+0

创建一个属性'ChosenStudent',其类型为'Student',它将包含所选项目。并像这样使用它'SelectedItem =“{Binding Path = DataContext.ChosenStudent,Mode = TwoWay,RelativeSource = {RelativeSource FindAncestor,AncestorType = {x:Type ListView}}}''。 – AnjumSKhan

+0

_“模型上的集合值不会改变”_ - 为什么要这样做?改变组合框中的选择不会重新排列集合的顺序,那么为什么'ClassroomStudents [0]'返回一个与以前不同的'Student'对象?甚至没有指出你的'ComboBox'控件似乎绑定到'Students'集合,而不是'ClassroomStudents'集合的事实。坦率地说,你一直都不清楚你期望或想要发生什么,或者为什么,尤其是考虑到你显然已经排除了一个单独的属性来绑定'SelectedItem'属性(根据之前的评论) –

+0

你不能两个-way绑定当前的DataContext,仅限上下文中的属性。你应该得到一个警告或错误与你的绑定'{绑定路径=。,模式=双向} – grek40

回答

0

我能想到的是包裹你的ClassroomStudents项目在选择容器的最简单的解决办法:

public class StudentContainer : INotifyPropertyChanged 
{ 
    public Student Item { get; set; } // TODO: INotifyPropertyChanged implementation 
} 

改变集合和初始化:

public ObservableCollection<StudentContainer> ClassroomStudents { get; set; } 
// ... 
ClassroomStudents.Add(new StudentContainer { Item = Students[0] }); 

更改XAML

<ComboBox          
    ItemsSource="{Binding Students, RelativeSource={ RelativeSource AncestorType=Window}}" 
    DisplayMemberPath="Name" 
    SelectedItem="{Binding Path=Item,Mode=TwoWay}" 
    > 

我希望这足以给你一个出发点。代码中存在一些与您的问题没有直接关系的问题,但可能需要一些注意力才能完成整个工作。

+0

这是完美的,正是我所需要的。谢谢! – Rodobodolfo