Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何根据画布的宽度wpf设置子对象在画布中的位置_C#_.net_Wpf_Xaml_Canvas - Fatal编程技术网

C# 如何根据画布的宽度wpf设置子对象在画布中的位置

C# 如何根据画布的宽度wpf设置子对象在画布中的位置,c#,.net,wpf,xaml,canvas,C#,.net,Wpf,Xaml,Canvas,假设画布子对象的值为left=50,当画布宽度为500时,其值为top=50。调整画布大小时,调整如何设置相对于画布宽度的左侧和顶部位置 如果用户在大窗口中运行应用程序或调整窗口大小,画布子对象的左侧和顶部位置就会混乱。如何重新排列画布子元素的左侧和顶部位置如果您只是将元素放在窗口上,然后给它们留有边距,它们将不会随窗口缩放。我建议将它们保存在一个网格元素中,该元素会自动缩放其内容。然后给出允许内容缩放的行/列定义。例如: 将调整大小以适应内容,而不是更多 而将占用所有剩余空间 编辑:阅读以了解

假设画布子对象的值为left=50,当画布宽度为500时,其值为top=50。调整画布大小时,调整如何设置相对于画布宽度的左侧和顶部位置


如果用户在大窗口中运行应用程序或调整窗口大小,画布子对象的左侧和顶部位置就会混乱。如何重新排列画布子元素的左侧和顶部位置如果您只是将元素放在窗口上,然后给它们留有边距,它们将不会随窗口缩放。我建议将它们保存在一个
网格
元素中,该元素会自动缩放其内容。然后给出允许内容缩放的行/列定义。例如:

将调整大小以适应内容,而不是更多

将占用所有剩余空间


编辑:阅读以了解更多信息。您可能需要处理xaml代码

我将提供一个建议,但由于问题没有给我们提供任何现有代码,因此在问题更新之前,我无法提供任何具体/完整的代码

如果使用MVVM模式正确完成拖放界面,可能会涉及一个
ItemsControl
(或从它派生的东西),其
ItemsPanelTemplate
是一个
Canvas
。绑定必须提供
左侧
顶部
位置,可能占画布尺寸的百分比,例如

...
<ItemsControl.ItemContainerStyle>
    <Style>
        ...
        <Setter Property="Canvas.Left">
            <Setter.Value>
                <MultiBinding Converter="{StaticResource RelativePositionConverter}">
                    <MultiBinding.Bindings>
                        <Binding Path="Left" />
                        <Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}" />
                    </MultiBinding.Bindings>
                </MultiBinding>
            </Setter.Value>
        </Setter>
        <Setter Property="Canvas.Top">
            <Setter.Value>
                <MultiBinding Converter="{StaticResource RelativePositionConverter}">
                    <MultiBinding.Bindings>
                        <Binding Path="Top" />
                        <Binding Path="ActualHeight" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}" />
                    </MultiBinding.Bindings>
                </MultiBinding>
            </Setter.Value>
        </Setter>
        ...
    </Style>
</ItemsControl.ItemContainerStyle>
...
。。。
...
...
...
然后,您需要创建一个类来实现
IMultiValueConverter
(我碰巧在该XAML中调用了
RelativePositionConverter
),该类将第一个值(相对位置;0和1之间的双值)乘以第二个值(画布的宽度或高度)以获得正确的位置。请注意,您无法真正实现
ConvertBack
,因此用于启用拖动功能的
Thumb
的代码必须进行类似的数学运算来设置备份值


有很多活动部件可以完成这一点,但我认为我已经提供了足够的信息,让您走上正确的道路。如果您对如何进行绑定、转换器、拇指、控件模板等有进一步的疑问,最好创建一个包含更具体信息的新问题。

您可以使用override OnProperty更改如下自定义画布:

 public class YourCustomCanvas : Canvas
{
    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);
        var ep = e.Property;
        if (ep != null)
        {
            if(ep.Name == "Left")
            foreach (FrameworkElement child in Children)
              SetLeft(child, GetLeft(child) / (double)e.OldValue * (double)e.NewValue);
            else if (ep.Name == "Top")
                foreach (FrameworkElement child in Children)
                    SetTop(child, GetTop(child) / (double)e.OldValue * (double)e.NewValue);
        }
    }
}
// Canvas canvas = new Canvas();
YourCustomCanvas canvas = new YourCustomCanvas();
然后在项目中使用画布的CustomCanvas istead,如下所示:

 public class YourCustomCanvas : Canvas
{
    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);
        var ep = e.Property;
        if (ep != null)
        {
            if(ep.Name == "Left")
            foreach (FrameworkElement child in Children)
              SetLeft(child, GetLeft(child) / (double)e.OldValue * (double)e.NewValue);
            else if (ep.Name == "Top")
                foreach (FrameworkElement child in Children)
                    SetTop(child, GetTop(child) / (double)e.OldValue * (double)e.NewValue);
        }
    }
}
// Canvas canvas = new Canvas();
YourCustomCanvas canvas = new YourCustomCanvas();

我们需要更多的背景。您是在使用画布作为某种拖放界面供用户放置东西,还是在尝试将UI制作成表单?如果你要制作一个标准的应用程序界面,使用类似于
Grid
StackPanel
的东西将在布局上做得更好。是的,在这里用户将动态地将控件拖放到画布上,用户可以在画布内移动控件。如何相对于画布宽度设置left和top您需要根据宽度更新left和top值。但是如果你将画布的宽度设置为500,那么当你调整窗口大小时,它不会改变,所以我真的不理解你的问题?我能理解,这个画布在网格内,这是我的xaml,那么你的问题是什么?我有画布,WARE用户将动态添加子项并在画布中移动它们。它类似于自由形式,用户将安排控件。我不是以这种方式实现的,我覆盖画布,并在resize事件中尝试根据画布的宽度更新画布的左侧和顶部。使用newCanvasLeft=(oldleft*new Width)/oldWidth,这不正确,我的方法正确吗?或者我必须使用MeasureOverride()或ArrangeOverride()方法?@GANI,很抱歉,您只给了我代码的一小部分。这将很难或不可能得到帮助。我想您可以循环并尝试调整所有子项在resize上的位置,但是。。。我真的不建议这样做。