C# 设置相对于 MainWindow 的 translatetransform X 和 Y 属性

2023-12-22

我有一个 Wrappanel 托管在 ItemsControl 中,它包装在滚动查看器中。包装面板中的项目由绑定填充。每个项目都有一个带有数据触发器的数据模板。该触发器应该将项目动画到屏幕中心。我试图使用translatetransform来做到这一点,但问题是translatetransform的X和Y属性是相对于项目本身而不是主机容器,所以每个项目都有不同的动画。正如这里所见:

webm 1 http://webmshare.com/play/jj39d webm 2 http://webmshare.com/play/dLj97

项目模板XAML:

<DataTemplate x:Key="CountryItemTemplate">
    <Grid 
        x:Name="gridMain"
        Height="Auto"
        Width="Auto"
        Margin="3"
        RenderTransformOrigin="0 0"
        Panel.ZIndex="{Binding IsVisible, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
        <materialDesign:Card 
            x:Name="cardMain" 
            Height="350" 
            Width="310"
            RenderTransformOrigin="0.5, 0.5"
            materialDesign:ShadowAssist.ShadowDepth="Depth1"
            UniformCornerRadius="3">
            <Grid Background="Transparent">
                <Grid.RowDefinitions>
                    <RowDefinition Height="50*"/>
                    <RowDefinition Height="50*"/>
                </Grid.RowDefinitions>
                <Rectangle
                    Grid.Row="0">
                    <Rectangle.Fill>
                        <ImageBrush ImageSource="{Binding ImageUrl, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
                    </Rectangle.Fill>
                </Rectangle>
                <TextBlock
                    Grid.Row="1"
                    Foreground="Black"
                    FontWeight="Regular"
                    FontSize="25"
                    HorizontalAlignment="Left"
                    VerticalAlignment="Top"
                    Margin="16 24 0 0"
                    Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
                <Button
                    Grid.Row="1"
                    Style="{DynamicResource MaterialDesignToolButton}"
                    Content="Edit"
                    FontSize="15"
                    Width="85"
                    Height="35"
                    HorizontalAlignment="Right"
                    VerticalAlignment="Bottom"
                    Margin="0 0 16 24"
                    Command="{Binding IsInEditModeToggleCommand}"/>
            </Grid>
            <materialDesign:Card.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </materialDesign:Card.RenderTransform>
        </materialDesign:Card>
    </Grid>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding IsInEditMode, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation
                            Storyboard.TargetName="cardMain"
                            Storyboard.TargetProperty="(UIElement.RenderTransform).Children[1].(TranslateTransform.X)"
                            To="300"
                            By="1"
                            Duration="0:0:2">
                            <DoubleAnimation.EasingFunction>
                                <ExponentialEase
                                    EasingMode="EaseInOut"
                                    Exponent="16"/>
                            </DoubleAnimation.EasingFunction>
                        </DoubleAnimation>
                        <DoubleAnimation
                            Storyboard.TargetName="cardMain"
                            Storyboard.TargetProperty="(UIElement.RenderTransform).Children[1].(TranslateTransform.Y)"
                            To="400"
                            By="1"
                            Duration="0:0:2">
                            <DoubleAnimation.EasingFunction>
                                <ExponentialEase
                                    EasingMode="EaseInOut"
                                    Exponent="16"/>
                            </DoubleAnimation.EasingFunction>
                        </DoubleAnimation>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

我尝试像这样使用 UIElement.TranslatePoint :

整个 UserControl 的一切都是:

<UserControl 
    x:Class="NikolaLukovic.CustomsOfficeApp.Desktop.Views.CountryUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:domain="clr-namespace:NikolaLukovic.CustomsOfficeApp.Desktop.DomainModels"
    xmlns:helpers="clr-namespace:NikolaLukovic.CustomsOfficeApp.Desktop.Helpers"
    xmlns:mahApps="http://metro.mahapps.com/winfx/xaml/controls"
    xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
    xmlns:validationRules="clr-namespace:NikolaLukovic.CustomsOfficeApp.Desktop.Helpers.ValidationRules"
    xmlns:views="clr-namespace:NikolaLukovic.CustomsOfficeApp.Desktop.Views"
    xmlns:viewModels="clr-namespace:NikolaLukovic.CustomsOfficeApp.Desktop.ViewModels"
    xmlns:local="clr-namespace:NikolaLukovic.CustomsOfficeApp.Desktop.Views"
    mc:Ignorable="d" 
    d:DesignHeight="600" 
    d:DesignWidth="900">
    <UserControl.CacheMode>
        <BitmapCache/>
    </UserControl.CacheMode>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding LoadDataCommand}" CommandParameter="{Binding ElementName=icMain}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <UserControl.DataContext>
        <viewModels:CountryViewModel/>
    </UserControl.DataContext>
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="../Resources/CountryItemStyle.xaml"/>
                <ResourceDictionary Source="../Resources/Icons.xaml"/>
                <ResourceDictionary Source="../Resources/MaterialDesignIcons.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Button.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Shadows.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.ToggleButton.xaml" />
            </ResourceDictionary.MergedDictionaries>
            <BooleanToVisibilityConverter x:Key="BoolToVisConverter"/>
        </ResourceDictionary>
    </UserControl.Resources>
    <materialDesign:DialogHost>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="100"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="100"/>
            </Grid.ColumnDefinitions>
            <ScrollViewer
                Grid.Row="0"
                Grid.Column="0"
                Grid.RowSpan="2"
                Grid.ColumnSpan="2"
                VerticalScrollBarVisibility="Auto">
                <ItemsControl
                    HorizontalContentAlignment="Stretch"
                    VerticalContentAlignment="Stretch"
                    x:Name="icMain"
                    ItemTemplate="{StaticResource CountryItemTemplate}"
                    ItemsSource="{Binding Countries, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapPanel/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </ScrollViewer>
            <Button
                Width="45"
                Height="45"
                Style="{DynamicResource MaterialDesignFloatingActionAccentButton}" 
                Grid.Column="1" 
                Grid.Row="1"
                HorizontalAlignment="Left"
                VerticalAlignment="Top"
                Margin="0 10 0 0">
                <Viewbox Width="24" Height="24">
                    <Canvas Width="24" Height="24">
                        <Path Data="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" Fill="White" />
                    </Canvas>
                </Viewbox>
            </Button>
        </Grid>
    </materialDesign:DialogHost>
</UserControl>

数据上下文视图模型:

public class CountryViewModel : BaseViewModel
    {
        private ObservableCollection<CountryItem> countries;
        private DelegateCommand<ItemsControl> loadDataCommand;

        public CountryViewModel ( )
        {
            ViewModelFinder.Add(this);
        }

        public ObservableCollection<CountryItem> Countries
        {
            get
            {
                return countries;
            }

            set
            {
                this.countries = value;
                this.NotifyPropertyChanged();
            }
        }

        public DelegateCommand<ItemsControl> LoadDataCommand
        {
            get
            {
                if ( this.loadDataCommand == null )
                    this.loadDataCommand = new DelegateCommand<ItemsControl>(async icMain => await LoadDataMethod(icMain));

                return this.loadDataCommand;
            }
        }

        private async Task LoadDataMethod (ItemsControl icMain)
        {
            if ( this.Countries == null )
            {
                var countries = await CountryService.Instance.GetAllAsync();
                this.Countries = new ObservableCollection<CountryItem>();
                var util = new Util();
                foreach ( var country in countries.Take(40) )
                {
                    var countryItem = new CountryItem
                    {
                        Name = country.Name,
                        Iso2 = country.Iso2,
                        IsoAlpha3 = country.IsoAlpha3,
                        IsoUnM49Numerical = country.IsoUnM49Numerical,
                        Id = country.Id
                    };
                    var imageBytes = await util.GetImageBytesAsync(country.CountryFlagUrl);
                    countryItem.ImageUrl = country.CountryFlagUrl;
                    this.Countries.Add(countryItem);
                    countryItem.This = icMain.ItemContainerGenerator.ContainerFromItem(countryItem) as UIElement;
                }
            }
        }
    }

表示包装面板中的项目的类:

public class CountryItem : ObservableObject
    {
        private bool isEnabled = true;
        private bool isInEditMode;
        private bool isVisible = true;
        private DelegateCommand isInEditModeToggleCommand;
        private string name;
        private string iso2;
        private string isoAlpha3;
        private int isoUnM49Numerical;
        private string imageUrl;
        private Guid id;
        private UIElement @this;

        public CountryItem ( )
        {

        }

        public bool IsEnabled
        {
            get
            {
                return isEnabled;
            }

            set
            {
                this.isEnabled = value;
                this.NotifyPropertyChanged();
            }
        }
        [Required(AllowEmptyStrings = false, ErrorMessage = "Name is required.")]
        public string Name
        {
            get
            {
                return this.name;
            }
            set
            {
                this.name = value;
                this.NotifyPropertyChanged();
            }
        }
        [Required(AllowEmptyStrings = false, ErrorMessage = "Iso2 is required.")]
        public string Iso2
        {
            get
            {
                return this.iso2;
            }
            set
            {
                this.iso2 = value;
                this.NotifyPropertyChanged();
            }
        }
        [Required(AllowEmptyStrings = false, ErrorMessage = "Iso Alpha3 is required.")]
        public string IsoAlpha3
        {
            get
            {
                return this.isoAlpha3;
            }
            set
            {
                this.isoAlpha3 = value;
                this.NotifyPropertyChanged();
            }
        }
        [Required(AllowEmptyStrings = false, ErrorMessage = "Iso Un M49 Numerical is required.")]
        public int IsoUnM49Numerical
        {
            get
            {
                return this.isoUnM49Numerical;
            }
            set
            {
                this.isoUnM49Numerical = value;
                this.NotifyPropertyChanged();
            }
        }

        public string ImageUrl
        {
            get
            {
                return imageUrl;
            }

            set
            {
                this.imageUrl = value;
                this.NotifyPropertyChanged();
            }
        }

        public Guid Id
        {
            get
            {
                return id;
            }
            set
            {
                this.id = value;
            }
        }

        public bool IsInEditMode
        {
            get
            {
                return isInEditMode;
            }

            set
            {
                this.isInEditMode = value;
                this.NotifyPropertyChanged();
            }
        }

        public DelegateCommand IsInEditModeToggleCommand
        {
            get
            {
                if ( this.isInEditModeToggleCommand == null )
                    this.isInEditModeToggleCommand = new DelegateCommand(IsInEditModeToggleMethod);

                return this.isInEditModeToggleCommand;
            }
        }

        public bool IsVisible
        {
            get
            {
                return isVisible;
            }

            set
            {
                this.isVisible = value;
                this.NotifyPropertyChanged();
            }
        }

        public UIElement This
        {
            get
            {
                return this.@this;
            }

            set
            {
                this.@this = value;
                this.NotifyPropertyChanged();
            }
        }

        private void IsInEditModeToggleMethod ( )
        {
            var countryViewModel = ViewModelFinder.FindOne<CountryViewModel>();
            countryViewModel.Countries.Where(x=>x.Id != this.Id).ToList().ForEach(ci => ci.IsVisible = false);
            this.This.TranslatePoint(new Point(400, 500), Application.Current.MainWindow)
            this.IsInEditMode = !this.IsInEditMode;
        }
    }

解决方案是从 xaml 中放弃故事板动画,并在项目对象中以编程方式执行它。当我创建这些项目来填充环绕面板时,我添加了对创建的 ContentPresenter 的引用,该 ContentPresenter 代表项目本身和根父级,在本例中是 UserControl。

需要引用的 ContentPresenter 来对项目进行动画处理。 需要引用根父 UserControl 来获取用户控件中项目的当前位置。

现在动画看起来像这样:

webm 3 http://webmshare.com/play/GyPQw webm 4 http://webmshare.com/play/YXbM5

我在 CountryItem 中添加了这个方法:

    private void AnimateToCenter ( )
    {

        var sbTranslate = new Storyboard();
        var daTranslateX = new DoubleAnimation();
        var daTranslateY = new DoubleAnimation();
        var duration = new Duration(TimeSpan.FromSeconds(2));

        daTranslateX.Duration = duration;
        daTranslateY.Duration = duration;
        sbTranslate.Duration = duration;

        var exponentialEase = new ExponentialEase();
        exponentialEase.EasingMode = EasingMode.EaseInOut;
        exponentialEase.Exponent = 16;

        daTranslateX.EasingFunction = exponentialEase;
        daTranslateY.EasingFunction = exponentialEase;

        sbTranslate.Children.Add(daTranslateX);
        sbTranslate.Children.Add(daTranslateY);

        Storyboard.SetTarget(daTranslateX, this.This);
        Storyboard.SetTarget(daTranslateY, this.This);

        this.This.RenderTransform = new TranslateTransform();

        Storyboard.SetTargetProperty(daTranslateX, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
        Storyboard.SetTargetProperty(daTranslateY, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));

        //get the current point of the selected item
        var currentPoint = this.This.TranslatePoint(new Point(), this.Parent);

        //get actual width and height of the parent so we can calculate to which position to calculate
        var parentWidth = (this.Parent as UserControl).ActualWidth;
        var parentHeight = (this.Parent as UserControl).ActualHeight;

        //get actual width and height of the item itself to center the item correctly
        //this is needed because the X and Y coordinates of the item are top and left
        var thisWidth = (this.This as ContentPresenter).ActualWidth;
        var thisHeight = (this.This as ContentPresenter).ActualHeight;

        //animate the item to the center of the screen
        daTranslateX.To = (parentWidth / 2) - currentPoint.X - (thisWidth / 2);
        daTranslateY.To = (parentHeight / 2) - currentPoint.Y - (thisHeight / 2);

        sbTranslate.Begin();
    }

它在这里被称为:

        private void IsInEditModeToggleMethod ( )
        {
            this.IsEllipseVisible = true;
            var countryViewModel = ViewModelFinder.FindOne<CountryViewModel>();
            countryViewModel.Countries.Where(x=>x.Id != this.Id).ToList().ForEach(ci => ci.IsVisible = false);
            this.IsInEditMode = !this.IsInEditMode;
            this.AnimateToCenter();
        }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 设置相对于 MainWindow 的 translatetransform X 和 Y 属性 的相关文章

  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • WPF 绑定 CompositeCollection 中的 MenuItem 不起作用

    我在将命令绑定到复合集合中的菜单项时遇到问题 这MenuItem是其一部分ContextMenu这是定义在UserControl Resources 问题是新标签的绑定不起作用 当我将 MenuItem 放置在复合集合之外时 它将起作用 有
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况

随机推荐