WPF: класс обновления, полученный из frameworkelement - PullRequest
1 голос
/ 13 августа 2011

Это работает очень странно.У меня есть некоторый класс, полученный из элемента framework.Это глупый код, потому что я хочу сделать его проще: P

public class Strange : FrameworkElement
{
    public DrawingVisual Visual;

    public Strange()
    {
        Visual = CreateDrawingVisualRectangle();
    }

    protected override Visual GetVisualChild(int index)
    {
        return Visual;
    }
    protected override int VisualChildrenCount
    {
        get
        {
            return 1;
        }
    }

    // Create a DrawingVisual that contains a rectangle.
    public DrawingVisual CreateDrawingVisualRectangle()
    {

        var drawingVisual = new DrawingVisual();

        DrawingContext drawingContext = drawingVisual.RenderOpen();
        var rect = new Rect(new Point(0, 0), new Size(100, 100));
        drawingContext.DrawRectangle(Brushes.Red, null, rect);
        drawingContext.Close();

        return drawingVisual;
    }
}

Далее я помещаю этот класс в Grid.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Button Click="Button_Click">Change Color</Button>
    <Test:Strange Grid.Column="1" x:Name="strange"/>
</Grid> 

 private void Button_Click(object sender, RoutedEventArgs e)
    {
        strange.Visual = strange.CreateDrawingVisualRectangle();
        var size = new Size(strange.ActualWidth, strange.ActualHeight);
        strange.Measure(size);
        strange.Arrange(new Rect(size));
        strange.UpdateLayout();
    }

Когда я нажал кнопку, странный объект перешел в первый столбец (он отображается при начале сетки).У меня есть больше логики в моем проекте, и мне нужно обновить странный объект, но он должен быть еще во втором столбце (там, где он был).

Что я сделал не так?

1 Ответ

4 голосов
/ 13 августа 2011

Когда вы вызываете Arrange для объекта, он перерисовывается в указанном вами месте относительно его родителя.Поскольку его родителем является сетка, (0,0, size.Width, size.Height) поместит его в верхний левый угол.

Чтобы решить вашу непосредственную проблему, вместо измерения и упорядочения,Вы должны просто позвонить InvalidateMeasure:

strange.Visual = strange.CreateDrawingVisualRectangle();
strange.InvalidateMeasure();

Однако я думаю, что вы подходите к этой проблеме немного неправильно.Я думаю, что вы хотите сделать, это переопределить OnRender, чтобы получить контроль.Это очень похоже на то, что вы делаете с DrawingVisual, за исключением того, что ваш FrameworkElement - это то, что рисуется:

protected override void OnRender(DrawingContext dc)
{            
    var rect = new Rect(new Point(0, 0), new Size(100, 100));
    dc.DrawRectangle(Brushes.Red, null, rect);
}

Я предполагаю, что у вас есть некоторые DependencyProperty, которые вы используете для управлениякак нарисован ваш Strange класс.Если вы зарегистрируете их с помощью свойства FrameworkPropertyMetadata.AffectsRender, это автоматически приведет к перерисовке класса.Например, это позволит вам установить Color для объекта Strange, и он будет автоматически перерисован при установке свойства:

public class Strange : FrameworkElement
{
    #region Color Dependency Property
    public static readonly DependencyProperty ColorProperty = 
      DependencyProperty.Register(
      "Color",
      typeof(Color),
      typeof(Strange),
      new FrameworkPropertyMetadata(Colors.Red, 
          FrameworkPropertyMetadataOptions.AffectsRender));

    public Color Color
    {
        get { return (Color)GetValue(ColorProperty); }
        set { SetValue(ColorProperty, value); }
    }
    #endregion 

    protected override void OnRender(DrawingContext dc)
    {            
        var rect = new Rect(new Point(0, 0), new Size(100, 100));
        dc.DrawRectangle(new SolidColorBrush(Color), null, rect);
    }
}
...