【问题标题】:WPF Bind UserControl Property inside of the DataTemplate of a GridViewColumn.CellTemplateWPF 在 GridViewColumn.CellTemplate 的 DataTemplate 中绑定 UserControl 属性
【发布时间】:2018-04-26 11:43:45
【问题描述】:

我试图弄清楚如何绑定自定义用户控件的属性,该控件位于列表视图控件的单元格模板内,但它不起作用。所有 DisplayMemberBinding 字段都按预期工作,我得到了正确的值,但在该自定义控件内部,没有任何更新。

WPF 列表视图控件

<ListView Margin="10" x:Name="lvHistory">
                <ListView.Resources>
                    <Style TargetType="{x:Type GridViewColumnHeader}">
                        <Setter Property="HorizontalContentAlignment" Value="Left" />
                    </Style>
                </ListView.Resources>
                <ListView.View>
                    <GridView>
                        <GridViewColumn Header="Database" Width="150" DisplayMemberBinding="{Binding ActiveBackup.Database.Name, Mode=TwoWay}"  />
                        <GridViewColumn Header="Start Time" Width="130" DisplayMemberBinding="{Binding ActiveBackup.StartTime, Mode=TwoWay}" />
                        <GridViewColumn Header="Time Elapsed" Width="100" DisplayMemberBinding="{Binding ActiveBackup.TimeElapsed, Mode=TwoWay}" />
                        <GridViewColumn Header="P2" Width="100" DisplayMemberBinding="{Binding Progress, Mode=TwoWay}" />
                        <GridViewColumn x:Name="progressColumn" Header="Progress" Width="150">
                            <GridViewColumn.CellTemplate>
                                <DataTemplate>
                                    <local:cProgressBarSmall x:Name="pr1" Value="{Binding Progress, Mode=TwoWay}" Visibility="Visible" />
                                </DataTemplate>
                            </GridViewColumn.CellTemplate>
                        </GridViewColumn>
                    </GridView>
                </ListView.View>
            </ListView>

cProgressBarSmall 控件中的代码隐藏。

public partial class cProgressBarSmall : UserControl
    {
        public ActiveBackup ActiveBackup { get; set; }

        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(decimal), typeof(cProgressBarSmall));

        private decimal _value;
        public decimal Value
        {
            get
            {
                return (decimal) GetValue(ValueProperty);
            }
            set
            {
                _value = value;
                SetValue(ValueProperty, value);
                p1.Value = value.ToDoubleNotNull();
                pLabel.Text = value.ToPercent(0);
                if (value == 0)
                {
                    p1.Visibility = Visibility.Hidden;
                    pLabel.Visibility = Visibility.Hidden;
                }
                else if (value.ToDoubleNotNull() >= p1.Maximum)
                {
                    pLabel.Text = "Finished!";
                    pLabel.Foreground = new SolidColorBrush(Colors.Black);
                }
            }
        }
    }
}

我找不到访问“pr1”的方法,因为它位于 DataTemplate 中,因此无法从代码隐藏中直接访问。绑定不成功吗?它前面的列(“P2”列)只是在我放入的测试列中,只是为了确保该值实际上正在更新并且它是正确显示的,但是“progressColumn”总是只显示默认值。

ListView.View > GridView > GridViewColumn > GridViewColumn.CellTemplate > DataTemplate 层次结构中的数据绑定有什么特别之处吗?

【问题讨论】:

    标签: wpf data-binding


    【解决方案1】:

    首先,如果您在 setter 中放置断点,您会发现它没有被绑定命中。这是因为 Binding 设置的是依赖属性,而不是 C# 属性。他们是不同的。带有 get/set 的 C# 属性是依赖属性的可选包装器。

    做到这一点的正确方法是很少或根本没有代码(后面的代码不是邪恶的;你只是不需要任何代码),而是use a binding in the usercontrol xaml to update the UI。您可以使用用户控件 XAML 中的样式触发器来隐藏和显示控件以及更新标签文本。您不需要任何代码。

    但这是将现有代码调整为可行的最简单方法。

        public decimal Value
        {
            get { return (decimal)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
    
        public static readonly DependencyProperty ValueProperty = 
            DependencyProperty.Register("Value", typeof(decimal), typeof(cProgressBarSmall), 
                new PropertyMetadata(0m, Value_ChangedCallback));
    
        //  Has to be static
        private static void Value_ChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((cProgressBarSmall)d).OnValueChanged();
        }
    
        private void OnValueChanged()
        {
            p1.Value = Value.ToDoubleNotNull();
            pLabel.Text = Value.ToPercent(0);
            if (Value == 0)
            {
                p1.Visibility = Visibility.Hidden;
                pLabel.Visibility = Visibility.Hidden;
            }
            else if (Value.ToDoubleNotNull() >= p1.Maximum)
            {
                pLabel.Text = "Finished!";
                pLabel.Foreground = new SolidColorBrush(Colors.Black);
            }
        }
    

    【讨论】:

    • 知道了。非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-10
    • 2017-02-18
    相关资源
    最近更新 更多