使用自定义控件,在Itemscontrol datatemplate中使用依赖项属性

时间:2015-02-04 23:45:36

标签: c# wpf mvvm

我正在尝试使用MVVM创建极坐标图。径向轴是风速,径向角是风向。我可以创建径向圆(椭圆)和径向速度轴标签。对于角度线(如轮辐),我创建了一个自定义控件,它只是一个末尾带有文本块的线(给出角度轴值)。但是,我无法让我的程序设置此自定义控件的属性,因此您无法在画布上看到它们(虽然它们在那里,但默认长度为零,默认文本为空)?

好的,所以我的diagram.xaml如下:

<Grid>
    <Grid.DataContext>
        <local:DiagramViewModel x:Name="ViewModel" />
    </Grid.DataContext>
    <Viewbox x:Name="myView"
             Stretch="Uniform"
             StretchDirection="Both">
        <ItemsControl ItemsSource="{Binding Points}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas Height="400" Width="400"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Canvas.Right" Value="{Binding Right}"/>
                    <Setter Property="Canvas.Left" Value="{Binding Left}"/>
                    <Setter Property="Canvas.Top" Value="{Binding Top}"/>
                    <Setter Property="Canvas.Bottom" Value="{Binding Bottom}"/>
                    <Setter Property="Canvas.ZIndex" Value="{Binding ZIndex}"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
            <ItemsControl.Resources>
                <DataTemplate DataType="{x:Type local:EllipseItem}">
                        <Ellipse Stroke="{Binding Stroke}"
                                 StrokeThickness="{Binding StrokeThickness}" 
                                 StrokeDashArray="{Binding StrokeDashArray}"
                                 Height="{Binding Height}"
                                 Width="{Binding Width}"/>
                    </DataTemplate>
                <DataTemplate DataType="{x:Type local:GridLineItem}">
                        <View:GridLineComponent Text="{Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                Length="{Binding Path=Length, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                GridHeight="{Binding Path=GridHeight, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                LineColour="{Binding Path=LineColour, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                TextColour="{Binding Path=TextColour, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                RenderTransform="{Binding RenderTransform}"
                                                RenderTransformOrigin="{Binding RenderTransformOrigin}"/>
                    </DataTemplate>
                <DataTemplate DataType="{x:Type local:TextBlockItem}">
                        <TextBlock Text="{Binding Text}"
                                   Foreground="{Binding Foreground}"
                                   FontSize="{Binding FontSize}"/>
                    </DataTemplate>
            </ItemsControl.Resources>
        </ItemsControl>
    </Viewbox>
</Grid>

我的viewmodel(DiagramViewModel)以及其他内容包含以下创建这些行的方法:

private void CreateAngularLines(double originMargin)
    {
        IList<GridLineItem> angularLine = new List<GridLineItem>();

        double increment , angularGridlineCount, angle, height, width;

        if (this.minorAngularIncrement == null)
            increment = (double)this.majorAngularIncrement;
        else
            increment = (double)this.minorAngularIncrement;

        angularGridlineCount = 360 / increment;
        height = 200;//half the length of the canvas
        width = 200;

        for (int i = 0; i < angularGridlineCount; i++)
        {
            angularLine.Add(new GridLineItem());

            angle = i * increment;
            if (angle == 0 || angle == 180)
                angularLine[i].Text = angle.ToString("000");
            else if (angle < 180)
                angularLine[i].Text = "G" + angle.ToString("000");
            else
                angularLine[i].Text = "R" + (360 - angle).ToString("000");

            angularLine[i].Length = height - originMargin;
            angularLine[i].GridHeight = height;
            angularLine[i].LineColour = this.LineColour;
            angularLine[i].TextColour = this.TextColour;

            angularLine[i].Left = width - 18;
            angularLine[i].Top = 0;
            angularLine[i].Right = width;
            angularLine[i].Bottom = height;
            angularLine[i].ZIndex = 1;

            angularLine[i].RenderTransformOrigin = new Point(0.5, 1);
            angularLine[i].RenderTransform = new RotateTransform(angle, 0, 0);
        }

        Points.Add(new CollectionContainer() { Collection = angularLine });
    }

GridLineItem类是一个简单的holder类,包含以下内容:

public class GridLineItem
{
    public GridLineItem()
    {
        this.RenderTransformOrigin = new Point(0.5, 1);
        this.RenderTransform = new RotateTransform(0, 0, 0);

        this.Left = double.NaN;
        this.Right = double.NaN;
        this.Top = double.NaN;
        this.Bottom = double.NaN;
    }

    public Brush LineColour { get; set; }
    public Brush TextColour { get; set; }
    public string Text { get; set; }
    public double Length { get; set; }
    public double GridHeight { get; set; }
    public Point RenderTransformOrigin { get; set; }
    public Transform RenderTransform { get; set; }

    public int ZIndex { get; set; }
    public double Left { get; set; }
    public double Right { get; set; }
    public double Top { get; set; }
    public double Bottom { get; set; }
}

现在这就是我认为我出错的地方。 GridlineComponent.xaml.cs文件包含以下内容:

public partial class GridLineComponent : UserControl, INotifyPropertyChanged
{
    public GridLineComponent()
    {
        InitializeComponent();
        this.DataContext = this;
    }
    public GridLineComponent(string text, double length, double gridHeight) : this()
    {
        this.Text = text;
        this.Length = length;
        this.GridHeight = gridHeight;
    }

    public Brush LineColour
    {
        get { return (Brush)GetValue(LineColourProperty); }
        set
        {
            SetValue(LineColourProperty, value);
            NotifyPropertyChanged("LineColour");
        }
    }
    public Brush TextColour
    {
        get { return (Brush)GetValue(TextColourProperty); }
        set
        {
            SetValue(TextColourProperty, value);
            NotifyPropertyChanged("TextColour");
        }
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set
        {
            if (value == null)
                SetValue(TextProperty, "");
            else
                SetValue(TextProperty, value); //"\u00B0";

            NotifyPropertyChanged("Text");
        }
    }
    public double Length
    {
        get { return (double)GetValue(LengthProperty); }
        set
        {
            SetValue(LengthProperty, value);
            NotifyPropertyChanged("Length");
        }
    }
    public double GridHeight
    {
        get { return (double)GetValue(GridHeightProperty); }
        set
        {
            SetValue(GridHeightProperty, value);
            NotifyPropertyChanged("GridHeight");
        }
    }

    public static readonly DependencyProperty TextColourProperty =
    DependencyProperty.Register(
        "TextColour",
        typeof(Brush),
        typeof(GridLineComponent),
        new PropertyMetadata(default(Brush), OnItemsPropertyChanged));

    public static readonly DependencyProperty LineColourProperty =
    DependencyProperty.Register(
        "LineColour",
        typeof(Brush),
        typeof(GridLineComponent),
        new PropertyMetadata(default(Brush), OnItemsPropertyChanged));

    public static readonly DependencyProperty TextProperty =
    DependencyProperty.Register(
        "Text",
        typeof(string),
        typeof(GridLineComponent),
        new PropertyMetadata(default(string), OnItemsPropertyChanged));

    public static readonly DependencyProperty LengthProperty =
    DependencyProperty.Register(
        "Length",
        typeof(double),
        typeof(GridLineComponent),
        new PropertyMetadata(default(double), OnItemsPropertyChanged));

    public static readonly DependencyProperty GridHeightProperty =
    DependencyProperty.Register(
        "GridHeight",
        typeof(double),
        typeof(GridLineComponent),
        new PropertyMetadata(default(double), OnItemsPropertyChanged));

    private static void OnItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        GridLineComponent source = d as GridLineComponent;
        // Do something...
    }
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

}

基本上这个GridLineComponent不遵循MVVM的规则。但我认为这是可以的,因为它是一种基本类型。它的xaml只是一个包含一行和一个TextBlock的网格。行的Y2和笔划属性绑定到xaml.cs(分别为Length和LineColour),文本块的前景和文本属性(分别为TextColour和Text)也是如此。

从我所看到的,这些线应该画,但不是。我认为它可能与依赖属性或由于空的OnItemsPropertyChanged处理程序有关。另外,当程序运行时,只访问GridlineComponent.xaml.cs的非参数构造函数(未设置属性)?

0 个答案:

没有答案