以数据网格为中心缩放

本文关键字:为中心 缩放 网格 数据网 数据 | 更新日期: 2023-09-27 18:15:37

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

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

下面是我的xhtml代码:

<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绑定的值。

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

提前感谢。

编辑:

这里是整个xhtml文件。

<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的组合

以数据网格为中心缩放

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

这是我之前回答过的一个类似问题的链接,你可以在答案

中找到行为类

在调整子

的大小时保持scrollviewer's的相对滚动条偏移量

因此,从上面链接的答案中获取advancedzoom类并将以下属性设置为滚动查看器

<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>

如果你发现数据网格或图像的大小太小或太大,然后尝试调整网格,图像或数据网格的宽度/高度,viewbox将相应地缩放