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

时间:2017-08-11 01:07:12

标签: c# .net wpf xaml canvas

让我们说canvas canvas的值为left = 50,top = 50当canvas的宽度= 500时。当canvas调整大小时,如何设置相对于画布宽度的左侧和顶部位置。

如果用户在大窗口中运行应用程序或调整窗口大小,则画布子项的左侧和顶部位置会混乱。如何重新排列画布儿童的左侧和顶部位置

2 个答案:

答案 0 :(得分:1)

您可以使用覆盖OnPropertyChanged制作自定义画布,如下所示:

CTE Scan on search_graph (cost=1705.74..1707.36 rows=81 width=40) (actual time=0.066..1.231 rows=6 loops=1)
 CTE search_graph
 -> Recursive Union (cost=0.00..1705.74 rows=81 width=40) (actual time=0.055..1.206 rows=6 loops=1)
 -> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.030..0.031 rows=1 loops=1)
 -> Hash Left Join (cost=102.95..170.41 rows=8 width=40) (actual time=0.226..0.370 rows=2 loops=3)
 Hash Cond: (sg."NODE" = cnt.node)
 Filter: (((be.flag_one = 1) AND (cno.node IS NULL)) OR ((be.flag_two = 1) AND (cnt.node IS NULL)))
 Rows Removed by Filter: 16
 -> Hash Join (cost=42.10..47.71 rows=136 width=56) (actual time=0.161..0.279 rows=18 loops=3)
 Hash Cond: (be.source_id = sg."NODE")
 Join Filter: (be.target_id <> ALL (sg."PATH"))
 -> Seq Scan on teste_bidirectional_edges be (cost=0.00..1.81 rows=41 width=16) (actual time=0.084..0.197 rows=54 loops=2)
 Filter: ((flag_one = 1) OR (flag_two = 1))
 -> Hash (cost=41.68..41.68 rows=34 width=44) (actual time=0.084..0.084 rows=1 loops=3)
 Buckets: 1024 Batches: 1 Memory Usage: 8kB
 -> Hash Right Join (cost=0.26..41.68 rows=34 width=44) (actual time=0.062..0.065 rows=1 loops=3)
 Hash Cond: (cno.node = sg."NODE")
 -> Seq Scan on teste_censored_nodes_one cno (cost=0.00..32.60 rows=2260 width=4) (actual time=0.029..0.034 rows=1 loops=2)
 -> Hash (cost=0.22..0.22 rows=3 width=40) (actual time=0.021..0.021 rows=1 loops=3)
 Buckets: 1024 Batches: 1 Memory Usage: 8kB
 -> WorkTable Scan on search_graph sg (cost=0.00..0.22 rows=3 width=40) (actual time=0.009..0.010 rows=1 loops=3)
 Rows Removed by Filter: 1
 -> Hash (cost=32.60..32.60 rows=2260 width=4) (actual time=0.074..0.074 rows=1 loops=1)
 Buckets: 4096 Batches: 1 Memory Usage: 33kB
 -> Seq Scan on teste_censored_nodes_two cnt (cost=0.00..32.60 rows=2260 width=4) (actual time=0.057..0.060 rows=1 loops=1)
Planning time: 1.924 ms
Execution time: 1.707 ms

然后使用YourCustomCanvas代替项目中的Canvas,如下所示:

 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);
        }
    }
}

答案 1 :(得分:0)

我将提供建议,但由于该问题使我们无法在现有代码方面使用任何内容,因此在更新问题之前,我无法提供任何特定/完整的代码。

拖放界面,如果使用MVVM模式正确完成,可能涉及ItemsControl(或从中派生的内容)ItemsPanelTemplateCanvas。绑定必须提供LeftTop展示位置,可能占画布尺寸的百分比,例如

...
<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中碰巧调用StaticResource的{​​{1}}),该类乘以第一个值(相对位置;两个值之间的值) 0和1)通过第二个值(画布的宽度或高度)来获得正确的位置。请注意,您无法真正实现RelativePositionConverter,因此启用拖动功能的ConvertBack代码必须使用类似的数学运算来设置支持值。

有许多活动部件可以实现这一目标,但我认为我已经提供了足够的信息来帮助您走上正确的道路。如果您对如何进行绑定,转换器,大拇指,控制模板等方面有进一步的疑问,最好使用更具体的信息创建新问题。