【问题标题】:How do I get WPF DataGrid and AutoCompleteBox's Selected Item to play nice?如何让 WPF DataGrid 和 AutoCompleteBox 的 Selected Item 发挥出色?
【发布时间】:2012-01-04 20:14:30
【问题描述】:

我在 WPF 表单上使用了 AutoCompleteBox 没有问题。现在我想在 WPF DataGrid 中做同样的事情。除了 SelectedItem 的设置器之外,几乎所有东西都有效。我看到 getter 被调用,但是在输入一个值并点击选项卡(或使用箭头键)之后,setter 永远不会被调用。在控制台输出中,我没有看到任何绑定错误。我希望有人能告诉我我做错了什么以及如何让 SelectedItem 在 ViewModel 类中的属性位于 DataGrid 中时触发该属性的 setter。首先是ViewModel类的sn-p:

    public static List<ImpaSimple> AllImpas { get { return ImpaListRepository.ImpaList; } }
    private ImpaSimple _selectedImpa;

    public ImpaSimple SelectedImpa
    {
        get { return _selectedImpa; }
        set
        {
            if (value == _selectedImpa) return;
            _selectedImpa = value;
            //Manually set Description and Unit fields because user can override the IMPA default values.
           // Description = _selectedImpa.Name;
            //TODO Set Units too
            RaisePropertyChanged("SelectedImpa");
        }
    }

XAML

在下面的 XAML 中,我在 LostFocus 的处理程序后面添加了一个代码作为临时解决方法。添加 UpdateSourceTrigger 属性也是尝试使其正常工作。

<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
    <TextBlock  Style="{StaticResource DataGridHeader}">LImpa</TextBlock>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <Hots:AutoCompleteBoxEx ToolTip="Start typing an IMPA number"
                                ItemsSource="{Binding AllImpas}"
                                Width="50"
                                HorizontalContentAlignment="Left"
                                FilterMode="StartsWith"
                                IsDropDownOpen="True"
                                IsTextCompletionEnabled="True"
                                LostFocus="ImpaBoxExLostFocus"
                                SelectedItem="{Binding SelectedImpa, 
                                                        Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            <Hots:AutoCompleteBoxEx.ItemTemplate>
                <DataTemplate>
                    <Grid Width="450">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50" />
                            <ColumnDefinition Width="275" />
                            <ColumnDefinition Width="50" />
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding ImpaId}"
                                   Grid.Column="0" />
                        <TextBlock Text="{Binding Name}"
                                   Grid.Column="1" />
                        <TextBlock Text="{Binding Unit}"
                                   Grid.Column="2" />
                    </Grid>
                </DataTemplate>
            </Hots:AutoCompleteBoxEx.ItemTemplate>
        </Hots:AutoCompleteBoxEx>

    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

【问题讨论】:

  • 在您的网格数据源中 - 您是否有任何带有预设 SelectedImpa 的项目,如果有,它是否正确显示该值?如果确实如此,那么就有机会了。使用 AutoCompleteBoxEx SelectedItem 实现拧紧。某些控件无法作为编辑器服务是典型的。你拥有它的源代码吗?
  • 我忘了我没有使用标准自动完成框。 AutoCompleteBoxEx 只是我通过 `public class AutoCompleteBoxEx : AutoCompleteBox' 创建的一个类,因此我可以将 SelectionChanged 事件连接到一个处理程序,当使用箭头键时该处理程序将滚动到视图中。所以是的,我有源代码,但功能来自 wpf 工具包 AutoCompleteBox。其他分析者的下一条评论。
  • ALSO 我想在这段旅程中的某个时刻,如果 SelectedImpa 具有非空值但发布的代码确实显示了自动完成框并显示数据也不起作用。我可以看到正在调用 getter,但自动完成文本框中没有显示任何值。它会链接一个错误的绑定值,除非我没有收到控制台输出错误。我尝试更改上下文,但确实会产生绑定错误。并且 ItemsSource 到 AllImpas 的绑定似乎在我输入时起作用,我看到了值列表,所以这让我认为数据上下文是正确的。
  • 没有值通常表明您的绑定没有被拾取。对于派生类,通常引用设计师不考虑继承场景(以及托管场景),所以我会检查您的子类的 SelectedValue 是否响应网格中的项目选择而改变。
  • 我将其更改为使用 std AutoCompleteBox 而不是我的 AutoCompleteBoxEx 但没有区别。当 AutoCompleteBox 或 AutoCompleteBoxEx not 在 DataGrid 中时没有问题。我同意这看起来像是一个绑定问题,但在过去绑定错误时,我总是会在“输出”窗格中收到此类错误的通知,但我没有收到任何消息。

标签: wpf data-binding wpfdatagrid autocompletebox


【解决方案1】:

啊,我想我知道那是什么 - 我称之为“害羞数据上下文”的缺陷 - 尝试设置你的 热点:AutoCompleteBoxEx DataContext 到:

DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type YourDataSourceItemType}}}"

检查它的方法是创建一个虚拟转换器并像这样使用它:

ItemsSource="{Binding Converter={StaticResource DummyConverter}}"

然后在其 Convert 中放置一个断点并检查该值。由于没有指定 Path - 输入值是 DataContext 本身,如果它为 null,那么它永远不会被设置/丢失。

【讨论】:

  • 正如写的那样,这不会编译,所以我假设你有 AncestorLevel 你的意思是 AncestorType,但它没有工作。网格的每一行都是视图模型类的一个实例,在这种情况下,该类是 OrderLineItemRowViewModel。所以我用 vm:OrderLineItemRowViewModel 替换了 YourDataSourceItemType。这会在 DataContext 上生成绑定源错误。看起来这应该找到该行上的类的实例。 DataGrid 的 ItemsSource 道具。是此类的 ObservableCollection 和 SelectedItem 道具。是此类的单个实例。
  • 确定不会 - 只需将其添加到您的
  • 这就是我放的地方。但你的意思是让我使用 AncestorType 而不是 AncestorLevel,对吗?
  • 考虑到这一点,绑定的行为就像它工作一样,但它的行为完全就像它处于OneWay模式一样。作为测试,我将模式更改为 OneWay,没有任何区别。我有一种感觉,即使我明确地设置了 Mode=TwoWay,也有一些东西覆盖了它。
猜你喜欢
  • 2011-07-17
  • 2013-08-01
  • 1970-01-01
  • 2010-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多