Search code examples
wpflistviewcelltemplate

Double Values in listView cell


I need to show old and new values in my ListView, when the record is changed. I mean each cell should show new value and old value. For now I'm doing so:

<GridViewColumn.CellTemplate>
    <DataTemplate>
         <StackPanel>
              <TextBlock Text="{Binding MyValue}"/>
              <TextBlock Margin="7,0,0,0" Text="{Binding old.MyValue}"/>
         </StackPanel>
    </DataTemplate>
</GridViewColumn.CellTemplate> 

for next column it will be:

<GridViewColumn.CellTemplate>
    <DataTemplate>
         <StackPanel>
              <TextBlock Text="{Binding MySecondValue}"/>
              <TextBlock Margin="7,0,0,0" Text="{Binding old.MySecondValue}"/>
         </StackPanel>
    </DataTemplate>
</GridViewColumn.CellTemplate>

But I have 10 columns and this is not so interesting to make a lot of copy-paste for all 10 columns.

Any ideas how this can be done more compact and more better?

The ideal variant I want is something like this:

<GridViewColumn.CellTemplate>
    <DataTemplate>
         <MySpecialWhatever NewValueText="{Binding MyValue}" OldValueText="{Binding old.MyValue}" > 
         </MySpecialWhatever>
    </DataTemplate>
</GridViewColumn.CellTemplate>

Solution

  • You can achieve your goal with custom UserControl like this.

    DoubleValuesCell.xaml

    <UserControl x:Class="WpfApplication1.DoubleValuesCell"
                 x:Name="root"
                 ...>
        <StackPanel>
            <TextBlock Text="{Binding NewValue, ElementName=root}"/>
            <TextBlock Margin="7,0,0,0" Text="{Binding OldValue, ElementName=root}"/>
        </StackPanel>
    </UserControl>
    

    DoubleValuesCell.xaml.cs

    public partial class DoubleValuesCell : UserControl
    {
        public static readonly DependencyProperty NewValueProperty = DependencyProperty.Register("NewValue", typeof(object), typeof(DoubleValuesCell));
    
        public static readonly DependencyProperty OldValueProperty = DependencyProperty.Register("OldValue", typeof(object), typeof(DoubleValuesCell));
    
        public object NewValue
        {
            get { return GetValue(NewValueProperty); }
            set { SetValue(NewValueProperty, value); }
        }
    
        public object OldValue
        {
            get { return GetValue(OldValueProperty); }
            set { SetValue(OldValueProperty, value); }
        }
    
        public DoubleValuesCell()
        {
            InitializeComponent();
        }
    }
    

    XXXWindow.xaml

    <Window x:Class="WpfApplication1.XXXWindow"
            xmlns:local="clr-namespace:WpfApplication1"
            ...>
        ...
            <GridViewColumn>
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <local:DoubleValuesCell NewValue="{Binding MyValue}" OldValue="{Binding old.MyValue}"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        ...
    </Window>
    

    UPDATE

    You can collapse second control with DataTrigger.

    <StackPanel>
        <TextBlock Text="{Binding NewValue, ElementName=root}"/>
        <TextBlock Margin="7,0,0,0" Text="{Binding OldValue, ElementName=root}">
            <TextBlock.Style>
                <Style TargetType="TextBlock">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding OldValue, ElementName=root}" Value="{x:Null}">
                            <Setter Property="Visibility" Value="Collapsed"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </StackPanel>
    

    The above code means the second TextBlock is collapsed if the binding source value (OldValue property) is null.