如何设置绑定í;ng在C#中

本文关键字:#237 ng 绑定 何设置 设置 | 更新日期: 2023-09-27 17:58:48

我读了一些书(galli),并在网站上做了一些研究。问题是我想我不明白。

我试图做的是创建一个自定义形状(六边形)的按钮。当用户单击它时,它应该更改"颜色"。

在找到这个和那个之后,我创建了以下内容:

 public class hexButton : System.Windows.Controls.Button
{
    public SolidColorBrush borderColor { get; set; }
    public SolidColorBrush fillColor {get;set;}
    public int Height { get; private set; }
    public int Width { get; private set; }
    public Point Location { get; private set; }
    private Hexagon hex;
    public hexButton() : this(50,0,0,Colors.Yellow, Colors.Brown){}    
    public hexButton(int sideLenght, int positionX, int positionY, Color border, Color fill):base()
    {
        borderColor = new SolidColorBrush(border);
        fillColor = new SolidColorBrush(fill);
        hex = new Hexagon(sideLenght, positionX, positionY);
        Binding binding = new Binding();
        binding.Path = new PropertyPath("FillProperty");
        binding.Source = fillColor;
        BindingOperations.SetBinding(hex.polygon, Polygon.FillProperty, binding);
        ControlTemplate t = new ControlTemplate(typeof(Button));
        FrameworkElementFactory fef = new FrameworkElementFactory(typeof(Polygon));
        fef.Name = "Polygon";
        fef.SetValue(Polygon.PointsProperty, hex.polygon.Points);
        fef.SetBinding(Polygon.FillProperty, binding); //doesent work
        fef.SetValue(Polygon.StrokeThicknessProperty, hex.polygon.StrokeThickness);
        //fef.SetValue(Polygon.FillProperty, fillColor); // works at least for the constructor
        fef.SetValue(Polygon.StrokeProperty, borderColor);
        t.VisualTree = fef;
        Style hexButtonStyle = new Style(typeof(Button));
        hexButtonStyle.Setters.Add(new Setter(Button.TemplateProperty, t));
        this.Style = hexButtonStyle;
        this.Height = hex.Y_Max - hex.Y_Min;
        this.Width = hex.X_Max - hex.X_Min;
        this.Location = hex.location;
    }

我还有一个六边形类:

    public class Hexagon
{
    private int _Height;
    private int _Diameter;
    private int _SideLenght;
    public Polygon polygon { get; set; }
    public int Y_Min { get; private set; }
    public int Y_Max { get; private set; }
    public int X_Min { get; private set; }
    public int X_Max { get; private set; }
    public Point location { get; set; }
    public Hexagon() : this(30) { }
    public Hexagon(int sideLenght): this (sideLenght,0,0) { }
    public Hexagon(int sideLenght, Point location): this(sideLenght,(int)location.X, (int)location.Y){}
    public Hexagon(int sideLenght, int locationX, int locationY)
    {
        if (sideLenght <= 0)
        {
            sideLenght = 30;
        }
        _SideLenght = sideLenght;
        calcHeight();
        calcDiameter();
        location = new Point(locationX, locationY);
        polygon = new Polygon();
        polygon.Points.Clear();
        polygon.StrokeThickness = 4;
        createHexPolygon();
    }
    private void calcHeight()
    {
        //h = (√3)s
        _Height = Convert.ToInt32(Math.Pow(3,0.5)*_SideLenght);
    }
    private void calcDiameter()
    {
        _Diameter = 2 * _SideLenght;
    }
    private void createHexPolygon()
    {   //        0           1
        //         __________
        //        /          '
        //       /            '
        //      /              '  2
        //    5 '              /
        //       '            /
        //        '__________/
        //        4           3
        Point p = new Point();
        p.X = _SideLenght / 2;
        p.Y = 0;
        p.X = p.X + location.X + 2; // +2 =offset von StrokeThickness (siehe konstruktor)
        p.Y = p.Y + location.Y + 2;
        polygon.Points.Add(p);
        p.X = _SideLenght + (_SideLenght / 2);
        p.Y = 0;
        p.X = p.X + location.X + 2;
        p.Y = p.Y + location.Y + 2;
        polygon.Points.Add(p);
        p.X = _Diameter;
        p.Y = _Height / 2;
        p.X = p.X + location.X + 2;
        p.Y = p.Y + location.Y + 2;
        polygon.Points.Add(p);
        p.X = _SideLenght + (_SideLenght / 2);
        p.Y = _Height;
        p.X = p.X + location.X + 2;
        p.Y = p.Y + location.Y + 2;
        polygon.Points.Add(p);
        p.X = _SideLenght / 2;
        p.Y = _Height;
        p.X = p.X + location.X + 2;
        p.Y = p.Y + location.Y + 2;
        polygon.Points.Add(p);
        p.X = 0;
        p.Y = _Height / 2;
        p.X = p.X + location.X + 2;
        p.Y = p.Y + location.Y + 2;
        polygon.Points.Add(p);
        X_Min = (int)polygon.Points[5].X;
        X_Max = (int)polygon.Points[2].X + 2;
        Y_Min = (int)polygon.Points[0].Y;
        Y_Max = (int)polygon.Points[3].Y + 2;
    }
}

为了以后使用(当点击按钮-属性更改事件是必要的),我想用它来重置绑定:

        private void SetBinding()
    {
        Binding binding = new Binding();
        binding.Path = new PropertyPath("FillProperty");
        binding.Source = fillColor;
        BindingOperations.SetBinding(hex.polygon, Polygon.FillProperty, binding);
    }

我认为问题出在这里:

Binding binding = new Binding();
        binding.Path = new PropertyPath("FillProperty");
        binding.Source = fillColor;
        BindingOperations.SetBinding(hex.polygon, Polygon.FillProperty, binding);
        //....
        fef.SetBinding(Polygon.FillProperty, binding);

1. Why is the binding not working?
2. What do I need to do to make it work?
3. I read somewhere (don't know where) that creating styles and bindings in code (behind) is not really recommended
    - What would be another way to do this?
    - Why is it not recommended?

如何设置绑定í;ng在C#中

在非常基本的级别上,绑定是通过使用UI元素的DataContext属性来完成的。例如,如果您有一个Person类:

public class Person
{
     public string FirstName {get;set;}
     public string LastName {get;set;}
}

然后,您可以使用绑定将这些属性绑定到UI元素,而无需显式设置它们。这方面的一个例子是,如果你有一个StackPanel

<StackPanel x:Name="MyStack" Orientation="Horizontal">
    <TextBlock Text="{Binding FirstName}"/>
    <TextBlock Text="{Binding LastName}"/>
</StackPanel>

此XAML将在设置的DataContext中查找任何名为FirstName或LastName的属性。因此,通过将DataContext设置为Person对象,它可以显示我们指定的数据。

MyStack.DataContext = new Person(){ FirstName = "Test", LastName = "Man"};

这将告诉StackPanel用"Test"answers"Man"填充这两个文本框。

此逻辑扩展到任何类型的UI对象,例如用于设置颜色的SolidColorBrush。如果您扩展Person类以接受FavColor属性的SolidColorBrush,那么您也可以通过为其设置绑定来设置面板的背景,即

<StackPanel x:Name="MyStack" Background="{Binding FavColor}" Orientation="Horizontal">

但是,如前所述,您确实希望将模型(包含要显示的数据的对象,如我们的Person、User或Shape等)和任何类型的View信息完全分离。为了进一步了解如何做到这一点,我将研究模型-视图-视图-模型(MVVM)模式,它主要关注XAML数据绑定。有很多好的教程,我用视频例子来帮助我理解,所以可能也值得搜索这些来扩展你的知识。

Binding binding = new Binding();
binding.Path = new PropertyPath("FillProperty");
binding.Source = fillColor;
BindingOperations.SetBinding(hex.polygon, Polygon.FillProperty, binding);

该代码创建了一个绑定,该绑定的SourceSolidColorBrush,其PathFillProperty

这意味着绑定将转到Source对象,并在该Source对象上查找名为FillProperty的属性,然后将该属性的值传递给多边形的Fill属性。

这不是您想要的:SolidColorBrush没有名为FillProperty的属性(什么都没有),也没有名为Fill的属性。Fill是目标属性,而不是源属性。你想要的是:

hex.polygon.Fill = fillColor;

在这种特殊情况下使用绑定是没有用的,因为fillColor是一个局部变量。您对属性使用绑定,以便在源更改时更新目标(和/或目标更改可能会更新源,具体取决于参数)。

但为了学习Binding是如何工作的,这也应该是你想要的:

Binding binding = new Binding();
binding.Source = fillColor;
BindingOperations.SetBinding(hex.polygon, Polygon.FillProperty, binding);

我看到一些关于Polygon.FillPropertyPolygon.Fill的混淆。Polygon.FillProperty是一个公共静态只读DependencyProperty对象,它描述了Polygon的Fill依赖属性的特性。Polygon还有一个名为Fill的正则属性,您可以直接使用它,如我上面所示。按照惯例,公共静态只读DependencyProperty对象的名称与概念依赖属性相同,后缀为"property",但这不是绝对必需的。