获取画布面板 WPF MVVM 的中心坐标

Get Center Coordinates Of Canvas Panel WPF MVVM

提问人:Gokhan 提问时间:11/17/2023 最后编辑:Gokhan 更新时间:11/21/2023 访问量:91

问:

我想用 mvvm 图案在画布中间画一个形状。

在后面的代码中,我通过使用 ActualWidth 和 ActualHeight 属性到达了中间点。

但是我在MVVM中无法执行此操作。如何从XAML实现ActualWidth和ActualHeight属性?

以下是 XAML 代码:

<Window x:Class="CanvasSampleMvvm.View.MainView"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:local="clr-namespace:CanvasSampleMvvm.View"
        xmlns:model="clr-namespace:CanvasSampleMvvm.Model"
        xmlns:vm="clr-namespace:CanvasSampleMvvm.ViewModel"
        mc:Ignorable="d"
        Title="MainView" Height="450" Width="800">

    <Window.Resources>
        <vm:MainViewVM x:Key="vm"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource vm}">

        <ItemsControl ItemsSource="{Binding Path=Shapes}">
            <ItemsControl.Resources>
                <DataTemplate DataType="{x:Type model:mShape}">
                    <Path Data="{Binding Geometry}" Stroke="{Binding Stroke}" Fill="{Binding Fill}" RenderTransform="{Binding Transform}" />
                </DataTemplate>
            </ItemsControl.Resources>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                  
                        <Canvas ClipToBounds="True" Background="Transparent" DataContext="{StaticResource vm}">
                        
                       </Canvas>
                
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style TargetType="ContentPresenter">
                    <Setter Property="Canvas.Left" Value="{Binding Path=XPos}" />
                    <Setter Property="Canvas.Top" Value="{Binding Path=YPos}" />
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>

    </Grid>
</Window>

以下是 MainView 模型代码:

public class MainViewVM : INotifyPropertyChanged
    {
        public ObservableCollection<mShape> Shapes { get; } = new ObservableCollection<mShape>();
        public MainViewVM()
        {
            // XPos abd YPos values has to be center coordinates of canvas panel
            Shapes.Add(new mShape
            {
                XPos = 100,
                YPos = 100,
                Stroke = new SolidColorBrush(Color.FromArgb(0xFF, 0x66, 0x66, 0x66)),
                Geometry = new EllipseGeometry { RadiusX = 50, RadiusY = 50 },
                Fill = (SolidColorBrush)new BrushConvert,r().ConvertFrom("#D3D3D3")

            });


        }
        
        private void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;

    }

这是模型类:

public class mShape
    {
        public double XPos { get; set; }
        public double YPos { get; set; }
        public Geometry Geometry { get; set; }
        public Brush Stroke { get; set; }
        public Brush Fill { get; set; }
    }

enter image description here

C# WPF XAML 画布 MVVM

评论

1赞 Andy 11/17/2023
我会考虑在原点绘制它并将变换渲染到中心。使用转换器将实际高度和宽度绑定到一半
0赞 Gokhan 11/17/2023
实际上我不明白。你能再解释一下吗?
0赞 Andy 11/18/2023
您需要提供最少的代码,标记可以演示您正在执行的操作。否则,您的帖子将被关闭。我希望看到被削减的视图模型和标记,我可以将其放入临时解决方案中,并且在运行时看起来就像您的图片一样。如果你有很多代码和标记,我建议你使用精简版本,而不是仅仅粘贴所有内容。
0赞 Gokhan 11/18/2023
代码已添加。

答:

1赞 mm8 11/21/2023 #1

如何从XAML实现ActualWidth和ActualHeight属性?

您需要实现一段代码来跟踪视图中这些属性的更改,并设置视图模型属性。

您可以在 GitHub 上查看此 SizeObserver 实现,以获取可实现此目的的示例。

它实现了可在 XAML 标记中绑定到的附加属性:

<Canvas SizeObserver.Observe="True"
        SizeObserver.ObservedWidth="{Binding YourViewModelWidthProperty, Mode=OneWayToSource}"
        SizeObserver.ObservedHeight="{Binding YourViewModelHeightProperty, Mode=OneWayToSource}">
        ... />