WPF 在 GridViewColumn.CellTemplate 的 DataTemplate 中绑定 UserControl 属性

Posted

技术标签:

【中文标题】WPF 在 GridViewColumn.CellTemplate 的 DataTemplate 中绑定 UserControl 属性【英文标题】:WPF Bind UserControl Property inside of the DataTemplate of a GridViewColumn.CellTemplate 【发布时间】: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 层次结构中的数据绑定有什么特别之处吗?

【问题讨论】:

【参考方案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);
        
    

【讨论】:

知道了。非常感谢您的帮助!

以上是关于WPF 在 GridViewColumn.CellTemplate 的 DataTemplate 中绑定 UserControl 属性的主要内容,如果未能解决你的问题,请参考以下文章

wpf窗体阴影

wpf窗体添加事件的地方在哪里?

wpf 带参数的用户控件,如何在xaml中引入

WPF 精修篇 Winform 嵌入WPF控件

winform 可以用wpf窗体吗

wpf怎么在遮罩层中加入控件