如何使用代码

时间:2018-03-07 12:51:58

标签: c# wpf data-binding

我一直在尝试在wpf中设置双向绑定。有一个用ContentControls填充的画布,每个画布都包含一个填充的矩形。通过拇指,每个ContentControl可以变大,因此可以更改width

这些ContentControls已由代码生成并存在于类(CanvasElement)中,该类用于其他计算。

我想在ContentControl类中设置CanvasElement属性宽度和公共双变量Width之间的双向绑定。当Thumb用于更改contentControl的宽度时,Width的{​​{1}}会更新,但另一种方式则无效。< / p>

这是我到目前为止所拥有的:

CanvasElement

以及:

 public class CanvasElement
{
    private double width;
    public double height;
    private Point location; // This is the upper left point of the rectangle
    public Brush color;
    public string UID;
    public ContentControl canvasElement;

    public CanvasElement(Point location, double width, double height, Brush color, string UID)
    {
        this.location = location;
        this.width = width;
        this.height = height;
        this.color = color;
        this.UID = UID;

        canvasElement = new ContentControl() { Width = this.width, Height = this.height, Uid = UID };
        Canvas.SetLeft(canvasElement, this.location.X);
        Canvas.SetTop(canvasElement, this.location.Y);

        canvasElement.Content = new Rectangle() {
            IsHitTestVisible = false,
            Fill = this.color,
            Stroke =Brushes.LightGray,
            StrokeThickness = 2,
            Margin =  new Thickness(0,5,0,5),
            RadiusX = 10,
            RadiusY = 10};
        addBinding();

    }

    private void addBinding()
    {
        Binding widthBinding = new Binding();
        widthBinding.Source = this;
        widthBinding.Path = new PropertyPath("Width");
        widthBinding.Mode = BindingMode.TwoWay;
        widthBinding.NotifyOnSourceUpdated = true;
        widthBinding.NotifyOnTargetUpdated = true;
        //widthBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        BindingOperations.SetBinding(canvasElement, ContentControl.WidthProperty, widthBinding);

    }




    public double Width
    {
        get
        {
            return width;
        }
        set
        {
            if(width != value)
            {
                width = value;
                OnPropertyChanged();
            }
        }
    }

我很感激能得到的每一个暗示!

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

正如克莱门斯在评论中指出的那样,ItemsControl是正确的方法。由于添加到画布中的UIElements不同,我需要添加ItemsControl.ItemTemplateSelectorItemsControlItemContainerStyleSelector

XAML

<AdornerDecorator ClipToBounds="True">
    <ItemsControl ItemsSource="{Binding CanvasElementList}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Canvas Background="FloralWhite"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyleSelector>
            <local:CustomStyleSelector>
                <local:CustomStyleSelector.CanvasStyle_TL>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Canvas.Left" Value="{Binding Path=X, Mode=TwoWay}"/>
                        <Setter Property="Canvas.Top" Value="{Binding Path=Y, Mode=TwoWay}"/>
                    </Style>
                </local:CustomStyleSelector.CanvasStyle_TL>
                <local:CustomStyleSelector.CanvasStyle_TR>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Canvas.Right" Value="{Binding Path=X, Mode=TwoWay}"/>
                        <Setter Property="Canvas.Top" Value="{Binding Path=Y, Mode=TwoWay}"/>
                    </Style>
                </local:CustomStyleSelector.CanvasStyle_TR>
                <local:CustomStyleSelector.CanvasStyle_BL>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Canvas.Left" Value="{Binding Path=X, Mode=TwoWay}"/>
                        <Setter Property="Canvas.Bottom" Value="{Binding Path=Y, Mode=TwoWay}"/>
                    </Style>
                </local:CustomStyleSelector.CanvasStyle_BL>
                <local:CustomStyleSelector.CanvasStyle_BR>
                    <Style TargetType="ContentPresenter">
                        <Setter Property="Canvas.Right" Value="{Binding Path=X, Mode=TwoWay}"/>
                        <Setter Property="Canvas.Bottom" Value="{Binding Path=Y, Mode=TwoWay}"/>
                    </Style>
                </local:CustomStyleSelector.CanvasStyle_BR>
                <local:CustomStyleSelector.LineStyle>
                    <Style TargetType="ContentPresenter">
                    </Style>
                </local:CustomStyleSelector.LineStyle>
            </local:CustomStyleSelector>
        </ItemsControl.ItemContainerStyleSelector>
        <ItemsControl.ItemTemplateSelector>
            <local:CustomTemplateSelectors>
                <local:CustomTemplateSelectors.LabelTemplate>
                    <DataTemplate>
                        <TextBlock
                                Text="{Binding Text}"
                                FontWeight="{Binding FontWeight}"
                                FontSize="{Binding FontSize}"/>
                    </DataTemplate>
                </local:CustomTemplateSelectors.LabelTemplate>
                <local:CustomTemplateSelectors.LineTemplate>
                    <DataTemplate>
                        <Line X1="{Binding X1}"
                                    X2="{Binding X2}"
                                    Y1="{Binding Y1}"
                                    Y2="{Binding Y2}"
                                    Stroke="{Binding Stroke}"
                                    StrokeThickness="{Binding StrokeThickness}"
                                    StrokeDashArray="{Binding StrokeDashArray}"/>
                    </DataTemplate>
                </local:CustomTemplateSelectors.LineTemplate>
                <local:CustomTemplateSelectors.CanvasElementTemplate>
                    <DataTemplate>
                        <ContentControl Width="{Binding Path=Width, Mode=TwoWay}" Height="{Binding Path=Height, Mode=TwoWay}" 
                                    Style="{StaticResource ResourceKey=DesignerItemStyle}"
                                    MouseDoubleClick="ContentControl_MouseDoubleClick">
                            <Rectangle Fill="{Binding Color}"
                                Stroke="LightGray"
                                StrokeThickness="2"
                                Margin="0,5,0,5"
                                RadiusX="10"
                                RadiusY="10"
                                IsHitTestVisible="False"/>
                        </ContentControl>
                    </DataTemplate>
                </local:CustomTemplateSelectors.CanvasElementTemplate>

            </local:CustomTemplateSelectors>

        </ItemsControl.ItemTemplateSelector>
    </ItemsControl>
</AdornerDecorator>

代码

在相应的.cs文件中有ObservableCollectionsCompositeCollection。后者是绑定到ItemsControl的元素。要添加新元素,您必须向Observable Collections

添加元素
CanvasElementList4Canvas = new ObservableCollection<CanvasElement>();
LineList4Canvas = new ObservableCollection<CustomLine>();
LabelList4Canvas = new ObservableCollection<LabelTextBlock>();

CanvasElementList = new CompositeCollection();
CanvasElementList.Add(new CollectionContainer() { Collection = CanvasElementList4Canvas });
CanvasElementList.Add(new CollectionContainer() { Collection = LineList4Canvas });
CanvasElementList.Add(new CollectionContainer() { Collection = LabelList4Canvas });

要设置绑定,此处显示CustomLine类。 CanvasElement和LabelTextBlock类以相同的方式设置。

CustomLine

public class CustomLine : INotifyPropertyChanged
{
    private double _X1;
    private double _X2;
    private double _Y1;
    private double _Y2;
    private int _strokeThickness = 3;
    private Brush _stroke = Brushes.Black;
    private DoubleCollection _strokeDashArray = new DoubleCollection() {  1.0, 0.0  };

    public double X1 { get { return _X1; } set { if (_X1 != value) { _X1 = value; NotifyPropertyChanged("X1"); } } }
    public double X2 { get { return _X2; } set { if (_X2 != value) { _X2 = value; NotifyPropertyChanged("X2"); } } }
    public double Y1 { get { return _Y1; } set { if (_Y1 != value) { _Y1 = value; NotifyPropertyChanged("Y1"); } } }
    public double Y2 { get { return _Y2; } set { if (_Y2 != value) { _Y2 = value; NotifyPropertyChanged("Y2"); } } }
    public int StrokeThickness { get { return _strokeThickness; } set { if (_strokeThickness != value) { _strokeThickness = value; NotifyPropertyChanged("StrokeThickness"); } } }
    public Brush Stroke { get { return _stroke; } set { if (_stroke != value) { _stroke = value; NotifyPropertyChanged("Stroke"); } } }
    public DoubleCollection StrokeDashArray { get { return _strokeDashArray; } set { if (_strokeDashArray != value) { _strokeDashArray = value; NotifyPropertyChanged("StrokeDashArray"); } } }



    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

最后需要自定义选择器才能在画布中使用正确的模板和正确的样式:

public class CustomTemplateSelectors : DataTemplateSelector
{
    public DataTemplate CanvasElementTemplate { get; set; }
    public DataTemplate LineTemplate { get; set; }
    public DataTemplate LabelTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is CanvasElement)
            return CanvasElementTemplate;
        else if (item is CustomLine)
            return LineTemplate;
        else if (item is LabelTextBlock)
            return LabelTemplate;
        else return base.SelectTemplate(item, container);
    }
}

public class CustomStyleSelector : StyleSelector
{
    public Style CanvasStyle_TL { get; set; }
    public Style CanvasStyle_TR { get; set; }
    public Style CanvasStyle_BL { get; set; }
    public Style CanvasStyle_BR { get; set; }
    public Style LineStyle { get; set; }

    public override Style SelectStyle(object item, DependencyObject container)
    {
        if (item is CanvasElement)
            return CanvasStyle_TL;
        else if (item is CustomLine)
            return LineStyle;
        else if (item is LabelTextBlock)
        {
            var tempItem = item as LabelTextBlock;
            if (tempItem.Tag == "TL")
                return CanvasStyle_TL;
            else if (tempItem.Tag == "TR")
                return CanvasStyle_TR;
            else if (tempItem.Tag == "BL")
                return CanvasStyle_BL;
            else if (tempItem.Tag == "BR")
                return CanvasStyle_BR;
            else return base.SelectStyle(item, container);
        }
        else return base.SelectStyle(item, container);
    }
}