【问题标题】:Binding within DataTemplate does not work on first load of viewDataTemplate 中的绑定在第一次加载视图时不起作用
【发布时间】:2020-04-08 12:18:53
【问题描述】:

我在尝试绑定到视图模型中的属性的自定义控件上有一个依赖项属性。该控件位于视图中的DataTemplate 内(UserControl)。但是,绑定似乎只有在视图加载后更改绑定特性时才起作用。

下面是视图 XAML 中内容的示例:

<dxb:BarStaticItem Alignment="Far">
    <dxb:BarStaticItem.ContentTemplate>
        <DataTemplate>
            <controls:AllMaxDateRangeCombo Grid.Row="1"
                                           DateRange="{Binding DataContext.WorkOrderDateRange, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=UserControl}}"
                                           TimeFrameType="Current"
                                           Width="150" />
        </DataTemplate>
    </dxb:BarStaticItem.ContentTemplate>
</dxb:BarStaticItem>

BarStaticItem 是一个 DevExpress 控件,用于在工具栏中放置“普通”控件。我在AllMaxDateRangeCombo 中定义的绑定在第一次加载视图时不起作用。但是在运行时(调试期间),如果要通过在属性名称末尾添加一个数字来更改属性名称,然后立即删除该数字,则绑定将开始工作。

由于缺乏更好的理解,我只能说绑定似乎在第一次加载时没有正确“连接”,或者它在某些部分准备好之前尝试。但是当我在运行时进行更改时,它突然被链接了。

我希望这足以让有人帮助我弄清楚这里发生了什么。

P.S.:使用 Snoop 工具,我可以看到控件的依赖属性 DateRange 在我进行运行时更改之前根本没有绑定。然后,出现一个绑定。因此,无论出于何种原因,我定义的绑定根本不会在第一次加载视图时启动。

编辑:在回答一个问题时,我将解释一些机制。 AllMaxDateRangeCombo 基本上是一个包含 LastMonth、Today、LastWeek 等选项的 ComboBox。进行选择时,将重新计算日期范围并将其分配给控件的 DateRange 依赖属性。由于这是我要绑定的属性,因此我希望 UI 视图模型的属性会随之更改。然后我会响应并更新 UI 数据。但该属性值永远不会改变。因此,要么绑定永远不会真正连接起来,要么无法通知更改。

【问题讨论】:

  • 我不知道解决方案,但我会投票赞成您的问题,因为我认为这是一个很好解释的问题,我也想知道解决方案。 PS:你可以上传项目或类似的东西(也许在 githiub 上)?如果我可以下载它进行调试,那就太好了。最好的问候
  • @AdrianEfford 谢谢。不幸的是,我无法上传。部分是因为这是一个巨大的项目,但也因为它是专有工作。
  • @DonBoitnott:你是说DateRange 属性最初没有设置吗?你是如何确认这一点的? WorkOrderDateRange 源属性的默认值是多少?确定和DateRange的默认值不一样?
  • @mm8 它有一个默认值,基本上是一个日期最小值/最大值。不,我要说的是,绑定似乎没有发生。该控件类似于组合框,当做出选择时(例如 LastMonth),DateRange 会相应地设置。我正在尝试响应该更改并更新 UI 数据,但我的视图模型的属性永远不会改变,因此我认为绑定并没有真正挂钩。或者至少它由于某种原因无法通知。
  • @DonBoitnott:如果您希望任何人能够指出原因,您需要提供此问题的repo

标签: c# wpf data-binding datatemplate


【解决方案1】:

这最终是由于控件中的值是如何更改的。在控件中,定义了这个依赖属性:

public static DependencyProperty DateRangeProperty = DependencyProperty.Register("DateRange", typeof(DateTimeRange), typeof(AllMaxDateRangeCombo), new PropertyMetadata(new DateTimeRange(DateTime.MinValue, DateTime.MaxValue)));
public DateTimeRange DateRange
{
    get => (DateTimeRange)GetValue(DateRangeProperty);
    set => SetValue(DateRangeProperty, value);
}

组合框选择改变后,该值被设置:

private void RecalculateDates()
{
    DateRange = new DateTimeRange(DateTime.MinValue, DateTime.MaxValue);
}

只要控件的使用不在DataTemplate 中,这在双向绑定中运行良好。但是一旦在DataTemplate中使用,那么只有这个版本有效:

SetCurrentValue(DateRangeProperty, new DateTimeRange(DateTime.MinValue, DateTime.MaxValue));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多