缩放数据网格居中

时间:2014-07-29 09:08:47

标签: c# wpf mvvm wpf-controls zooming

我必须编写一个能够同时放大和缩小两个不同图层的应用程序。

背景图层包含一个在缩放过程中始终居中的图像。但是,第二层基于父容器的上边缘。

这是我的XAML代码:

<ScrollViewer Visibility="{Binding LeerformularIsVisible}" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
    <Grid>
        <Image x:Name="DZBackgroundImage" Source="{Binding DZGridBackground}" Stretch="None" />
        <DataGrid ColumnWidth="7" MinColumnWidth="7" RowHeight="15" BorderBrush="{x:Null}" AutoGenerateColumns="True" CanUserAddRows="False"
            Visibility="{Binding GridIsVisible}" ItemsSource="{Binding DPGridCR}" Margin="5,50,70,0" Background="Transparent" RowBackground="Transparent"
            HeadersVisibility="None" SelectionUnit="Cell" CanUserResizeRows="False" HorizontalGridLinesBrush="{Binding LineBrush}" VerticalGridLinesBrush="{Binding LineBrush}">

            <i:Interaction.Behaviors>
                <ViewModel:IgnoreMouseWheelBehavior />
            </i:Interaction.Behaviors>

            <DataGrid.CellStyle>
                <Style TargetType="DataGridCell">
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Background" Value="#325EB226" />
                            <Setter Property="BorderBrush" Value="#325EB226" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.CellStyle>

            <DataGrid.ContextMenu>
                <ContextMenu>
                    <MenuItem Command="{Binding AddFieldDefinitionCommand}" Header="Feld hinterlegen" Icon="pack://application:,,,/Images/Designer/field.png" />
                    <MenuItem Command="{Binding AddFunctionCommand}" Header="Funktion hinterlegen" Icon="pack://application:,,,/Images/Designer/function.png" />
                    <MenuItem Command="{Binding RemoveFieldDefinitionCommand}" Header="Aktuelle Felddefinition entfernen" Icon="pack://application:,,,/Images/Designer/remove_field.png" />
                    <MenuItem Command="{Binding CutCommand}" Header="Ausschneiden" Icon="pack://application:,,,/Images/Zwischenablage/FI_Ausschneiden_16x16.png" />
                    <MenuItem Command="{Binding CopyCommand}" Header="Kopieren" Icon="pack://application:,,,/Images/Zwischenablage/FI_Kopieren_16x16.png" />
                    <MenuItem Command="{Binding PasteCommand}" Header="Einfügen" Icon="pack://application:,,,/Images/Zwischenablage/FI_Einfuegen_16x16.png" />
                </ContextMenu>
            </DataGrid.ContextMenu>

        </DataGrid>

        <Grid.LayoutTransform>
            <ScaleTransform ScaleX="{Binding ZoomFactor}" ScaleY="{Binding ZoomFactor}" />
        </Grid.LayoutTransform>
    </Grid>
</ScrollViewer>

我从我的视图模型中获取了ZoomFactor绑定的值。

我的目标是同时缩放两个图层并重叠。

提前致谢。

修改 这是整个XAML文件。

<UserControl x:Class="Controls.DZLeerformularGrid"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:ViewModel="clr-namespace:ViewModel;assembly=ViewModel"
    xmlns:Behaviors="clr-namespace:ViewModel.Behaviors;assembly=ViewModel"
    xmlns:Extension="clr-namespace:Controls"
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="300"
    x:Name="DZLeerformularGridControl">

    <ScrollViewer Behaviors:AdvancedZooming.KeepInCenter="true" Visibility="{Binding LeerformularIsVisible}" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <Viewbox RenderTransformOrigin="0.5, 0.5" Stretch="Uniform">
            <Grid>
                <Image x:Name="DZBackgroundImage" Source="{Binding DZGridBackground}" Stretch="None" />
                <DataGrid ColumnWidth="7" MinColumnWidth="7" RowHeight="15" BorderBrush="{x:Null}" AutoGenerateColumns="True" CanUserAddRows="False"
            Visibility="{Binding GridIsVisible}" ItemsSource="{Binding DPGridCR}" Margin="5,50,70,0" Background="Transparent" RowBackground="Transparent"
            HeadersVisibility="None" SelectionUnit="Cell" CanUserResizeRows="False" HorizontalGridLinesBrush="{Binding LineBrush}" VerticalGridLinesBrush="{Binding LineBrush}">

                    <i:Interaction.Behaviors>
                        <Behaviors:IgnoreMouseWheelBehavior />
                    </i:Interaction.Behaviors>

                    <DataGrid.CellStyle>
                        <Style TargetType="DataGridCell">
                            <Style.Triggers>
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter Property="Background" Value="#325EB226" />
                                    <Setter Property="BorderBrush" Value="#325EB226" />
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </DataGrid.CellStyle>

                    <DataGrid.ContextMenu>
                        <ContextMenu>
                            <MenuItem Command="{Binding AddFieldDefinitionCommand}" Header="Feld hinterlegen" Icon="pack://application:,,,/Images/Designer/field.png" />
                            <MenuItem Command="{Binding AddFunctionCommand}" Header="Funktion hinterlegen" Icon="pack://application:,,,/Images/Designer/FI_Taschenmesser_16x16.png" />
                            <MenuItem Command="{Binding RemoveFieldDefinitionCommand}" Header="Aktuelle Felddefinition entfernen" Icon="pack://application:,,,/Images/Designer/remove_field.png" />
                            <MenuItem Command="{Binding CutCommand}" Header="Ausschneiden" Icon="pack://application:,,,/Images/Zwischenablage/FI_Ausschneiden_16x16.png" />
                            <MenuItem Command="{Binding CopyCommand}" Header="Kopieren" Icon="pack://application:,,,/Images/Zwischenablage/FI_Kopieren_16x16.png" />
                            <MenuItem Command="{Binding PasteCommand}" Header="Einfügen" Icon="pack://application:,,,/Images/Zwischenablage/FI_Einfuegen_16x16.png" />
                        </ContextMenu>
                    </DataGrid.ContextMenu>

                </DataGrid>
            </Grid>

            <Viewbox.RenderTransform>
                <ScaleTransform ScaleX="{Binding ZoomFactor}" ScaleY="{Binding ZoomFactor}" />
            </Viewbox.RenderTransform>
        </Viewbox>

    </ScrollViewer>

</UserControl>    

以下是我的ViewModel的C#代码:

using System.Collections.Generic;
using System.Data;
using System.Windows.Media;
using System.Windows.Input;
using ViewModelBase;
using System.Windows;

namespace ViewModel
{
    public class DZLeerformularGridViewModel : ViewModelBase.ViewModelBase
    {
        #region Fields
        #region Command Fields
        private RelayCommand addFieldDefinition;
        private RelayCommand removeFieldDefinition;
        private RelayCommand addFunction;
        private RelayCommand cutCommand;
        private RelayCommand copyCommand;
        private RelayCommand pasteCommand;
        #endregion

        private string leerformularIsVisible;
        private string dzGridBackground;
        private string gridIsVisible;
        private SolidColorBrush lineBrush;
        private DataTable dpGridCR;
        private double zoomFactor;
        #endregion

        public DZLeerformularGridViewModel()
        {
            LineBrush = Brushes.LightGray;
        }

        #region Properties
        public string LeerformularIsVisible
        {
            get { return leerformularIsVisible; }
            set
            {
                if (leerformularIsVisible != value)
                {
                    leerformularIsVisible = value;
                    OnPropertyChanged("LeerformularIsVisible");
                }
            }
        }

        public string DZGridBackground
        {
            get { return dzGridBackground; }
            set
            {
                if (dzGridBackground != value)
                {
                    System.Drawing.Image img = System.Drawing.Image.FromFile(value);
                    if (img.Height > img.Width)
                        generateColsAndRows(94, 70);    // DIN A4 Hochformat
                    else
                        generateColsAndRows(70, 94);    // DIN A4 Querformat

                    dzGridBackground = value;
                    OnPropertyChanged("DZGridBackground");
                }
            }
        }

        public string GridIsVisible
        {
            get { return gridIsVisible; }
            set
            {
                if (gridIsVisible != value)
                {
                    gridIsVisible = value;
                    OnPropertyChanged("GridIsVisible");
                }
            }
        }

        public SolidColorBrush LineBrush
        {
            get { return lineBrush; }
            set
            {
                if (lineBrush != value)
                {
                    if (!value.Equals(Brushes.LightGray) || !value.Equals(Brushes.Gray) || ! value.Equals(Brushes.LightSlateGray) || !value.Equals(Brushes.SlateGray) ||
                    !value.Equals(Brushes.Black) || !value.Equals(Brushes.Red) || !value.Equals(Brushes.DarkGray))
                        lineBrush = Brushes.LightGray;
                    else
                        lineBrush = value;

                    OnPropertyChanged("LineBrush");
                }
            }
        }

        public DataTable DPGridCR
        {
            get { return dpGridCR; }
            set
            {
                if (dpGridCR != value)
                {
                    dpGridCR = value;
                    OnPropertyChanged("DPGridCR");
                }
            }
        }

        public double ZoomFactor
        {
            get { return zoomFactor; }
            set
            {
                if (zoomFactor != value)
                {
                    zoomFactor = value;
                    OnPropertyChanged("ZoomFactor");
                }
            }
        }
        #endregion

        #region Command Properties
        public ICommand AddFieldDefinitionCommand
        {
            get
            {
                if (addFieldDefinition == null)
                    addFieldDefinition = new RelayCommand(p => ExecuteAddFieldDefinitionCommand());

                return addFieldDefinition;
            }
        }

        public ICommand RemoveFieldDefinitionCommand
        {
            get
            {
                if (removeFieldDefinition == null)
                    removeFieldDefinition = new RelayCommand(p => ExecuteRemoveFieldDefinitionCommand());

                return removeFieldDefinition;
            }
        }

        public ICommand AddFunctionCommand
        {
            get
            {
                if (addFunction == null)
                    addFunction = new RelayCommand(p => ExecuteAddFunctionCommand());

                return addFunction;
            }
        }

        public ICommand CutCommand
        {
            get
            {
                if (cutCommand == null)
                    cutCommand = new RelayCommand(p => ExecuteCutCommand());

                return cutCommand;
            }
        }

        public ICommand CopyCommand
        {
            get
            {
                if (copyCommand == null)
                    copyCommand = new RelayCommand(p => ExecuteCopyCommand());

                return copyCommand;
            }
        }

        public ICommand PasteCommand
        {
            get
            {
                if (pasteCommand == null)
                    pasteCommand = new RelayCommand(p => ExecutePasteCommand());

                return pasteCommand;
            }
        }
        #endregion

        #region Methods
        private void generateColsAndRows(int amountOfCols, int amountOfRows)
        {
            DataTable table = new DataTable();
            List<DataColumn> cols = new List<DataColumn>();
            for (int i = 0; i < amountOfCols; i++)
            {
                DataColumn column = new DataColumn();
                column.ReadOnly = true;
                table.Columns.Add(column);
                cols.Add(column);
            }

            for (int i = 0; i < amountOfRows; i++)
            {
                DataRow row = table.NewRow();
                foreach (DataColumn col in cols)
                    row[col] = " ";

                table.Rows.Add(row);
            }

            DPGridCR = table;
        }
        #endregion

        #region Command Methods
        private void ExecuteAddFieldDefinitionCommand()
        {
            MessageBox.Show("Add field definition");
        }

        private void ExecuteRemoveFieldDefinitionCommand()
        {
            MessageBox.Show("Remove field definition");
        }

        private void ExecuteAddFunctionCommand()
        {
            MessageBox.Show("Add function");
        }

        private void ExecuteCutCommand()
        {
            MessageBox.Show("Cut");
        }

        private void ExecuteCopyCommand()
        {
            MessageBox.Show("Copy");
        }

        private void ExecutePasteCommand()
        {
            MessageBox.Show("Paste");
        }
        #endregion
    }
}

放大图像时,不会出现水平滚动条。当我缩小图像时,垂直滚动条不会消失。这种效果是由RenderTransform的使用造成的。如果我使用LayoutTransform,则DataGrid会绑定到GridViewBox的上边缘。我怎么能解决这个问题?在我看来,我需要LayoutTransformRenderTransfrom的组合。

1 个答案:

答案 0 :(得分:1)

您可以创建附加行为并将其附加到滚动查看器。因此,该行为将检测内容大小的变化,并将内容保持在滚动查看器的中心

这里是我之前回答的类似问题的链接,您可以在答案中找到该行为类

Maintain scrollviewer's relative scrollbar offset when resizing child

所以从上面的链接中的答案中取出AdvancedZooming类,并将以下属性设置为滚动查看器

<ScrollViewer Visibility="{Binding LeerformularIsVisible}" 
              HorizontalScrollBarVisibility="Auto" 
              VerticalScrollBarVisibility="Auto"
              l:AdvancedZooming.KeepInCenter="True">

其中l:指项目的命名空间。这就是在缩放时将内容保持在中心所需的一切

修改

    <ScrollViewer Visibility="{Binding LeerformularIsVisible}"
                  HorizontalScrollBarVisibility="Auto"
                  VerticalScrollBarVisibility="Auto"
                  l:AdvancedZooming.KeepInCenter="True">
        <Viewbox>
            <Grid>
                <Image x:Name="DZBackgroundImage"
                       Source="{Binding DZGridBackground}" 
                       Stretch="None" />
                <DataGrid>
                 ...
                </DataGrid>
            </Grid>
            <Viewbox.LayoutTransform>
                <ScaleTransform ScaleX="{Binding ZoomFactor}"
                                ScaleY="{Binding ZoomFactor}" />
            </Viewbox.LayoutTransform>
        </Viewbox>
    </ScrollViewer>

如果您发现datagrid或图片的大小太小或太大,请尝试调整网格,图片或数据网格的宽度/高度,视图框会相应缩放