在xaml中绑定Rect宽度和高度

时间:2016-01-27 09:30:00

标签: c# wpf xaml viewport rect

我正试图在Rect中绑定ViewPort的宽度和高度,如下所示:

<VisualBrush.Viewport>
    <Rect Width="{Binding Path=MyWidth}" Height="{Binding Path=MyHeight}"/>
</VisualBrush.Viewport>

我的绑定在其他地方工作正常但在这里我收到以下错误消息:

  

A&#39;绑定&#39;无法设置“宽度”&#39;类型&#39; Rect&#39;的属性。 A&#39;绑定&#39;只能在DependencyObject的DependencyProperty上设置。

修改我理解错误消息。我的问题是如何解决它。如何绑定rect的高度和宽度?

2 个答案:

答案 0 :(得分:5)

使用像这样的MultiBinding:

<VisualBrush.Viewport>
    <MultiBinding>
        <MultiBinding.Converter>
            <local:RectConverter/>
        </MultiBinding.Converter>
        <Binding Path="MyWidth"/>
        <Binding Path="MyHeight"/>
    </MultiBinding>
</VisualBrush.Viewport>

使用这样的多值转换器:

public class RectConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return new Rect(0d, 0d, (double)values[0], (double)values[1]);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

答案 1 :(得分:-2)

更新答案: Rect是一个结构,高度和宽度是不依赖属性(参见屏幕截图),因此它们不能绑定到任何东西。

enter image description here

以下是使用依赖属性和绑定的方法。

具有依赖属性的

MyRect类

 public class MyRect : DependencyObject,INotifyPropertyChanged
{
    public MyRect()
    {            
        this.Rect = new Rect(0d, 0d, (double)Width, (double)Height);      
    }      

    private Rect rect;

    public Rect Rect
    {
        get { return rect; }
        set 
        {
            rect = value;
            RaiseChange("Rect");
        }
    }

    public double Height
    {
        get { return (double)GetValue(HeightProperty); }
        set { SetValue(HeightProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Height.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty HeightProperty =
        DependencyProperty.Register("Height", typeof(double), typeof(MyRect), new UIPropertyMetadata(1d, OnHeightChanged));

    public static void OnHeightChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue != null)
        {
            var MyRect = (dp as MyRect);
            var hight = Convert.ToDouble(e.NewValue);
            MyRect.Rect = new Rect(0d, 0d, MyRect.Rect.Width, hight);                
        }
    }

    public double Width
    {
        get { return (double)GetValue(WidthProperty); }
        set { SetValue(WidthProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Width.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty WidthProperty =
        DependencyProperty.Register("Width", typeof(double), typeof(MyRect), new UIPropertyMetadata(1d, OnWidthChanged));

    public static void OnWidthChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue != null)
        {
            var MyRect = (dp as MyRect);
            var width = Convert.ToDouble(e.NewValue);
            MyRect.Rect = new Rect(0d, 0d, width, MyRect.Rect.Height);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaiseChange(string prop)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }

}  

查看:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {           
        InitializeComponent();
        MyRect = new TabControl.MyRect();            
    }

    private MyRect myRect;
    public MyRect MyRect
    {
        get { return myRect; }
        set { myRect = value; RaiseChange("MyRect");}
    }             

    private void MySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        if (MyRect != null)
        {
            MyRect.Height = e.NewValue/10;
            MyRect.Width = e.NewValue/10;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaiseChange(string prop)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }
}

XAML:

<Window x:Class="TabControl.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
    xmlns:local="clr-namespace:TabControl"
    Title="MainWindow" Height="450" Width="525"       
    DataContext="{Binding RelativeSource={RelativeSource Self}}"        
    >
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="80*"/>
        <RowDefinition Height="80"/>
    </Grid.RowDefinitions>        
    <Rectangle Name="recLogin" Height="300"  Width="400" DataContext="{Binding MyRect}" >
        <Rectangle.Fill>
            <VisualBrush TileMode="None" Viewport="{Binding Rect}">                    
                <VisualBrush.Visual>
                    <ScrollViewer Height="30" Width="100">
                        <Button Content="Transparent" Height="30"  Width="80" />
                    </ScrollViewer>
                </VisualBrush.Visual>
            </VisualBrush>
        </Rectangle.Fill>
    </Rectangle>        
    <Slider Maximum="20" x:Name="MySlider" Value="4" TickFrequency="1" Grid.Row="1"  TickPlacement="TopLeft" ValueChanged="MySlider_ValueChanged" />
</Grid>

输出:

Larger

Smaller