简体   繁体   中英

Bind Rect Width and Height in xaml

I am trying to bind the width and height of a Rect in a ViewPort like this:

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

My binding works fine elsewhere but here I get the following error message:

A 'Binding' cannot be set on the 'Width' property of type 'Rect'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

Edit I understand the error message. My question is how to work around it. How do I bind the height and width of the rect?

Use a MultiBinding like this:

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

with a multi-value converter like this:

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

Updated Answer: Rect is an struct and Height and Width are not dependency properties (see screen shot), so they can't be bound to anything.

在此输入图像描述

Here is a way to do it using Dependency Property and Binding .

MyRect Class with Dependency Properties:

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

}  

View:

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>

Output:

较大的

较小

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM