1
votes

I'm trying to make a custom control which is basically a TextBox that sits above a datagrid column header and displays the total number in the datagrid column. The control library consists of two custom-controls: DataGridColumnTotal contains the textbox, which also holds references to the DataGrid and ItemsSource. The other is called DataGridHeaderTotalControl, which is basically a style that targets the DataGridColumnHeader. This style places the DataGridColumnTotal control above the existing DatagridColumnHeader and binds the DataGrid and DataGridItemsSource fields from the DataGridColumnTotal control to the Datagrid and ItemsSource fields.

I'm currently just trying to get the TextBox to show if the IsTotalVisible dependency property is set, but it will not update when I try to set it in MainWindow.xaml. I don't have any code in place that displays the total value because I haven't gotten that far yet.

The problem occurs in MainWindow.xaml, when trying to set ctl:DataGridColumnTotal.IsTotalVisible="True" in the dataGridText column. The IsTotalVisible property is not getting set to true. But when I set the default value of the dependency property to true, the total textboxes will show.

DataGridColumnTotal.cs

////////////////////////////////////////////////////////////////////
//DataGridColumnTotal.cs
////////////////////////////////////////////////////////////////////
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Collections;

namespace RiskControlLibrary
{
    public class DataGridColumnTotal : Control
    {
        static DataGridColumnTotal()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridColumnTotal), new FrameworkPropertyMetadata(typeof(DataGridColumnTotal)));
        }

        public static bool GetIsTotalVisible(
            DependencyObject target)
        {
            return (bool)target.GetValue(IsTotalVisibleProperty);
        }

        public static void SetIsTotalVisible(
            DependencyObject target, bool value)
        {
            target.SetValue(IsTotalVisibleProperty, value);
        }

        public static DependencyProperty IsTotalVisibleProperty =
        DependencyProperty.RegisterAttached("IsTotalVisible", typeof(bool), typeof(DataGridColumnTotal), 
        new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));

    }

    [ValueConversion(typeof(bool), typeof(Visibility))]
    public class BoolToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if ((bool)value)
                return Visibility.Visible;
            else
                return Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new Exception("Not Implemented.");
        }
    }
}

DataGridHeaderTotalControl.cs

////////////////////////////////////////////////////////////////////
//DataGridHeaderTotalControl.cs
////////////////////////////////////////////////////////////////////
using System.Windows;
using System.Windows.Controls;

namespace RiskControlLibrary
{
    public class DataGridHeaderTotalControl : Control
    {
        static DataGridHeaderTotalControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridHeaderTotalControl), new FrameworkPropertyMetadata(typeof(DataGridHeaderTotalControl)));
        }
    }
}

Generic.xaml

////////////////////////////////////////////////////////////////////
//Generic.xaml
////////////////////////////////////////////////////////////////////
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:RiskControlLibrary"
    xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    xmlns:s="clr-namespace:System;assembly=mscorlib">

    <Style TargetType="{x:Type local:DataGridColumnTotal}">
        <Style.Resources>
            <local:BoolToVisibilityConverter x:Key="booleanToVisibilityConverter" />
        </Style.Resources>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:DataGridColumnTotal}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <TextBox
                            x:Name="PART_TextBoxTotal"
                            IsReadOnly="True"
                            VerticalAlignment="Top"
                            VerticalContentAlignment="Center"
                            Text="{Binding Total,
                                RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:DataGridColumnTotal}}}"
                            Visibility="{Binding IsTotalVisible, RelativeSource={RelativeSource TemplatedParent},
                            Converter={StaticResource booleanToVisibilityConverter}}"
                         >
                        </TextBox>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style TargetType="{x:Type DataGridColumnHeader}"
           x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:DataGridHeaderTotalControl},
           ResourceId=DataGridHeaderTotalControlStyle}">
        <Setter Property="Template">

            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">

                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>

                        <local:DataGridColumnTotal Margin="1" Grid.Column="0" Grid.Row="0"/>

                            <theme:DataGridHeaderBorder Grid.Column="0" Grid.Row="1" SortDirection="{TemplateBinding SortDirection}"
                                     IsHovered="{TemplateBinding IsMouseOver}"
                                     IsPressed="{TemplateBinding IsPressed}"
                                     IsClickable="{TemplateBinding CanUserSort}"
                                     Background="{TemplateBinding Background}"
                                     BorderBrush="{TemplateBinding BorderBrush}"
                                     BorderThickness="{TemplateBinding BorderThickness}"
                                     Padding ="{TemplateBinding Padding}"
                                     SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
                                     SeparatorBrush="{TemplateBinding SeparatorBrush}">

                            <TextBlock Grid.Column="0" Grid.Row="1"  Text="{TemplateBinding  Content}" 
                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                       TextWrapping="Wrap"></TextBlock>

                        </theme:DataGridHeaderBorder>

                    </Grid>

                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

MainWindow.xaml

////////////////////////////////////////////////////////////////////
//MainWindow.xaml
////////////////////////////////////////////////////////////////////
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:app="clr-namespace:WpfApplication1"
        xmlns:ctl="clr-namespace:RiskControlLibrary;assembly=RiskControlLibrary"
        Title="MainWindow" Height="341" Width="452"
        Loaded="Window_Loaded">
    <Grid>
        <DataGrid 
            Name="m_dgOrder"
            ItemsSource="{Binding ListPos}"
            GridLinesVisibility="None"
            AutoGenerateColumns="False"
            IsReadOnly="True"
            Background="White"
            CanUserResizeRows="False"
            HeadersVisibility="Column"
            RowHeaderWidth="0"
            ColumnHeaderStyle="{StaticResource {ComponentResourceKey 
            TypeInTargetAssembly={x:Type ctl:DataGridHeaderTotalControl}, 
            ResourceId=DataGridHeaderTotalControlStyle}}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Symbol" Binding="{Binding Path=Symbol}"/>
                <DataGridTextColumn Header="Pos" Binding="{Binding Path=Pos}" ctl:DataGridColumnTotal.IsTotalVisible="True"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
1
To much code to look trough, but from what i see is you are trying to use a dependency property as an attached property, is that intended? I think you are looking for inherited attached properties.dowhilefor
I'm not sure if it should be attached. I tried using RegisterAttached, but that didn't work either. Would it need to be an attached property based on how it is set in MainWindow.xaml?Alex
From what i see is that you have a DataGridTextColumn and you set ctl:DataGridColumnTotal.IsTotalVisible="True" which clearly is the syntax for an attached property. But the property is not attached . Furthermore, it isn't inherited so any child DataGridColumnTotal classes can't make use of the property, which i guess is what you want. So make it Attached AND give it FrameworkPropertyMetadataOptions.Inherits instead of None. And see if that works. You also might need to adjust your bindings for the attached property.dowhilefor
Unfortunately that did not work. I changed it to this: public static DependencyProperty IsTotalVisibleProperty = DependencyProperty.RegisterAttached("IsTotalVisible", typeof(bool), typeof(DataGridColumnTotal), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));Alex
I agree with @dowhilefor, this is a bit too much code. You might get someone willing to debug this for you, but if not I recommend you cut it down as much as you can, remove everything that's not directly relevant to your problem, and then you'll have a much better chance of getting an answer.Roman Starkov

1 Answers

0
votes

I was registering the IsTotalVisible property to the wrong class. Instead of DataGridColumnTotal it should've been DataGridTextColumn.