control margin properties depending on another con

2019-09-17 04:22发布

问题:

I'm trying to show two canvas control in a grid in my wpf applike this way. the second_canvas.margin.left will be the same as first_canvas.margin.right . but it can't be done since margin property can't be used as a variable. So I tried "Thickness". but I can't convert first_canvas.margin.right to a thickness variable since it's a double type. So is there any work around for this?

回答1:

You could write a dedicated value converter:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;

namespace WpfMagic
{
    class EditableMarginConverter : IValueConverter
    {
        private double GetMarginPartValue(Thickness margin, string defaultValue, IDictionary<string, string> instructions)
        {
            string sourceValue;
            string value = instructions.TryGetValue(defaultValue, out sourceValue) ? sourceValue : defaultValue;

            double numericalValue;
            if (double.TryParse(value, out numericalValue))
            {
                return numericalValue;
            }

            return value == "left" ? margin.Left :
                   value == "top" ? margin.Top :
                   value == "right" ? margin.Right :
                   margin.Bottom;
        }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Thickness inputMargin = (Thickness)value;

            IDictionary<string, string> instructions = (parameter as string).Split()
                                                                            .Select(s => s.Split('='))
                                                                            .ToDictionary(t => t[0].ToLowerInvariant(), t => t[1].ToLowerInvariant());            

            Thickness outputMargin = new Thickness
            {
                Left = GetMarginPartValue(inputMargin, "left", instructions),
                Top = GetMarginPartValue(inputMargin, "top", instructions),
                Right = GetMarginPartValue(inputMargin, "right", instructions),
                Bottom = GetMarginPartValue(inputMargin, "bottom", instructions)
            };

            return outputMargin;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

And you would use it like this:

<StackPanel xmlns:local="clr-namespace:WpfMagic" Orientation="Horizontal">
    <StackPanel.Resources>
        <local:EditableMarginConverter x:Key="marginConverter"></local:EditableMarginConverter>
    </StackPanel.Resources>
    <Canvas x:Name="first_canvas"
            Width="100"
            Height="100"
            Margin="0 0 10 0"
            Background="Red">
    </Canvas>
    <Canvas x:Name="second_canvas"
            Width="100"
            Height="100"
            Background="Green"
            Margin="{Binding Margin,
                                ElementName=first_canvas,
                                Converter={StaticResource marginConverter},
                                ConverterParameter='Left=Right Right=0'}">
    </Canvas>
</StackPanel>

This a reusable way of doing it, but if it's a one-shot you probably should use some procedural plumbing, unless you are dogmatic and want to have perfect XAML.



回答2:

I implemented it simply this way...

int right = system.convert.ToInt32(first_canvas.margin.right)
second_canvas.margin = new thickness(left = right)