Combite的Selecteditem无法在datagrid中工作

时间:2012-08-21 17:38:42

标签: wpf combobox

我有一个Datagrid,其中一列是Combobox。问题是:如果Combobox在Datagrid之外,SelectedItem将运行良好,但如果相同的组合代码在网格内部,则不会工作。这是代码。

<StackPanel x:Name="stackPanel" Grid.Row="2" Background="White" Width="{Binding Width, ElementName=lvwPPVEvents}" Margin="0,0,0,1.875" >
        <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}, Path=DataContext.TestNumberofInstallments}" 
                  SelectedItem="{Binding Path=DataContext.TestInstall, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}},UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"/>
        <DataGrid ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" 
               ItemsSource="{Binding FilteredOrderedEvents,UpdateSourceTrigger=PropertyChanged,NotifyOnSourceUpdated=True}"
              SelectedItem="{Binding EventSelected}" CanUserReorderColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" 
              CellStyle="{StaticResource ClearlstItmContainerStyle}" AlternatingRowBackground="LightGray" MaxHeight="125"
              AlternationCount="2" SelectionMode="Single" Background="White"  AutoGenerateColumns="False" Margin="0,2"
                  HorizontalGridLinesBrush="White" Width="{Binding ActualWidth, ElementName=stackPanel}" HorizontalAlignment="Left" HorizontalContentAlignment="Stretch">
            <DataGrid.Columns>
                <DataGridTextColumn Width="50" Header="Status" Binding="{Binding Path= Status}" IsReadOnly="True"  />
                <DataGridTextColumn Width="60" Header="Order ID" Binding="{Binding Path= EventID}" IsReadOnly="True"/>
                <DataGridTextColumn Width="140" Header="Title" Binding="{Binding Path= Desc}" IsReadOnly="True"/>
                <DataGridTextColumn Width="120" Header="Date / Time" Binding="{Binding Path= StartDate}" IsReadOnly="True"/>
                <DataGridTextColumn Width="60" Header="Channel" Binding="{Binding Path= Channels}" IsReadOnly="True"/>
                <DataGridTextColumn Width="50" Header="Cost" Binding="{Binding Path= Cost,StringFormat=N2}" IsReadOnly="True"/>
                <!--<DataGridComboBoxColumn Header="Install" Width="Auto" ItemsSource="{Binding colNumberofInstallments}"/>-->
                <DataGridTemplateColumn Header="Install">
                    <!--<DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate>
                            <wpf:IntegerUpDown Value="{Binding NumberOfInstallments}" FormatString="N0" Increment="1" Maximum="{Binding Max}" Minimum="1"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>-->

                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <!--<TextBlock Text="{Binding NumberOfInstallments}"/>-->
                            <ComboBox ItemsSource="{Binding Path=DataContext.TestNumberofInstallments,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}" 
                                      SelectedItem="{Binding Path=DataContext.TestInstall, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}},UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Width="37" Header="Max" Binding="{Binding Path= Max}" IsReadOnly="True"/>
            </DataGrid.Columns >
        </DataGrid>
    </StackPanel>

2 个答案:

答案 0 :(得分:0)

它不起作用,主要是因为DataGridTemplateColumn不是可视树的一部分。因此,RelativeSource并不意味着该上下文中的任何内容。

你可以做一些简单的hackery:

    <DataGrid.Resources>
    <TextBlock x:Key="TempHack" DataContext="{YOUR ACTUAL BINDING HERE}"/>
   </DataGrid.Resources>

然后你可以像这样引用它:

 <DataGridTemplateColumn Header="{Binding Source={StaticResource TempHack}}" />

答案 1 :(得分:0)

有许多不同的控件可以被视为UserControl,因此我怀疑您没有使用UserControl绑定获得正确的RelativeSource

我建议您使用UserControl的完整类名而不是仅仅尝试在VisualTree中找到最接近的UserControl

<ComboBox 
    ItemsSource="{Binding DataContext.TestNumberofInstallments, 
        RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}}" 
    SelectedItem="{Binding DataContext.TestInstall, 
        RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}}" />

我做了一个快速测试,似乎工作得很好,但令我惊讶的是我无法在绑定中使用ElementName。可能ChrisDD is correct关于ElementName无法使用DataGridTemplateColumn,因为与VisualTree有关,但您绝对可以在RelativeSource中使用DataGridTemplateColumn {1}}

<StackPanel x:Name="RootPanel">

    <ComboBox ItemsSource="{Binding ElementName=RootPanel, Path=DataContext.Test}"
              SelectedItem="{Binding ElementName=RootPanel, Path=DataContext.SelectedTest}"
              DisplayMemberPath="TestValue"/>

    <DataGrid ItemsSource="{Binding Test}">
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type StackPanel}}, Path=DataContext.Test}"
                                  SelectedItem="{Binding RelativeSource={RelativeSource AncestorType={x:Type StackPanel}}, Path=DataContext.SelectedTest}"
                                  DisplayMemberPath="TestValue"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</StackPanel>

你应该注意的一件事是WPF通过引用而不是值来比较对象,因此SelectedItem必须指向内存中与ItemsSource中的项完全相同的引用,或者它不会被视为匹配并被选中。

例如,

ItemsSourceProperty = new ObservableCollection<SomeObject>()
{
    new SomeObject(1),
    new SomeObject(2),
    new SomeObject(3)
};

SelectedItemProperty = ItemsSourceProperty.FirstOrDefault(); // Works
SelectedItemProperty = new SomeObject(1); // Won't work