WPF绑定GridViewColumn.CellTemplate

时间:2017-11-13 17:39:40

标签: wpf data-binding

我试图弄清楚如何绑定放置在列表视图控件的单元格模板内的自定义用户控件的属性,但它无法正常工作。所有DisplayMemberBinding字段都按预期工作,并且我获得了正确的值,但在该自定义控件内部,没有任何内容正在更新。

WPF LIstView控件

<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控件中的Code-Behind。

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);
                }
            }
        }
    }
}

我无法找到一种方法来访问&#34; pr1&#34;因为它在DataTemplate中,因此无法从代码隐藏中直接访问。绑定不起作用吗?它之前的列(&#34; P2&#34;列)就在我输入的测试列中,只是为了确保该值实际上正在更新并且它正确显示,但是&#34; progressColumn& #34;始终只显示默认值。

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

1 个答案:

答案 0 :(得分:1)

首先,如果你在你的setter中放置一个断点,你会发现它没有受到绑定的影响。那是因为Binding设置了依赖属性,而不是C#属性。他们是不同的。带有get / set的C#属性是依赖属性的可选包装器。

这样做的正确方法是背后很少或没有代码(背后的代码不是邪恶的;你只是不需要任何代码),但是use a binding in the usercontrol xaml to update the UI。您可以在usercontrol 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);
        }
    }