2010-12-21 4 views
5

내가, 내가 외부 소스로 이동 높이 (100)의 Canvas 및 컨트롤의로드에서 폭 1920WPF ActualWidth 제로

이있는 사용자 제어 할 수 있습니다, 텍스트 파일을 다운로드에 TextBlock들 추가 캔버스. 그런 다음 TextBlockCanvas에 추가 한 다음에 계산 목적으로 너비를 가져야하지만 ActualWidth 속성은 항상 0 인 경우를 제외하고는 잘 작동하는 선택 윤곽 스크롤 효과를 만들고 싶습니다.

private readonly LinkedList<TextBlock> textBlocks = new LinkedList<TextBlock>(); 

public LocalNewsControl() 
{ 
    Loaded += LocalNewsControlLoaded; 
} 

private void LocalNewsControlLoaded(object sender, RoutedEventArgs e) 
{ 
    LoadDataContext(); 
} 

private void LoadDataContext() 
{ 
    DataContext = new NewsItemsViewModel((exception) => LoadNewsItems()); 
} 

private void LoadNewsItems() 
{ 
    var viewModel = (NewsItemsViewModel)DataContext; 

    NewsCanvas.Children.Clear(); 
    textBlocks.Clear(); 

    foreach (var newsViewModel in viewModel.NewsItems) 
    { 
     var tb = new TextBlock 
     { 
      Text = newsViewModel.Headline, 
      FontSize = 28, 
      FontWeight = FontWeights.Normal, 
      Foreground = Brushes.Black 
     }; 

     NewsCanvas.Children.Add(tb); 

     Canvas.SetTop(tb, 20); 
     Canvas.SetLeft(tb, -999); 

     textBlocks.AddLast(tb); 
    } 

    Dispatcher.BeginInvoke(new Action(() => 
    { 
     var node = textBlocks.First; 

     while (node != null) 
     { 
      if (node.Previous != null) 
      { 
       //THIS IS WHERE ActualWidth is always ZERO 
       var left = Canvas.GetLeft(node.Previous.Value) + node.Previous.Value.ActualWidth + Gap; 
       Canvas.SetLeft(node.Value, left); 
      } 
      else 
       Canvas.SetLeft(node.Value, NewsCanvas.Width + Gap); 

      node = node.Next; 
     } 
    })); 
} 
+1

TextBlock에 표시되지 않으며 ActualWidth 속성이 없으므로로드되지 않습니다. Itemscontrol과 비슷한 문제를 해결했지만 캔버스에 대해 잘 모르겠습니다. LayoutUpdated, SizeChanged 등과 같은 이벤트를 시도하십시오. – vorrtex

답변

3

발송자 호출을 유지하려면 우선로드 우선 순위를 설정하면로드 된 이벤트와 동일한 시간이 호출되며 값이 있어야합니다. BeginInvoke에는 우선 순위를 갖는 과부하가 있습니다.

+0

그 덕분에 많은 도움이되었습니다. – Mark

1

모든 ControlActualHeight하거나>Measured>Arranged>RenderedLoaded을 전에 ActualWidth은 항상 0이됩니다 : 여기

몇 가지 코드입니다.

귀하의 경우, 의 Loaded 또는 SizeChanged 이벤트를 사용하는 것이 좋습니다.

+0

많은 텍스트 블록이 있지만 마지막으로 추가 된 Loaded 이벤트에 가입해야합니다. – Mark

+0

나는 네가 옳은 것 같아! 이 'TextBlock' 컨트롤을'StackPanel'에'Horizontal' 오리엔테이션으로 추가하고 그 패널을 스크롤하지 않는다면 말입니다. 이 경우,'Panel'의 이벤트 만 처리해야합니다. – decyclone

0

TextBlock의 레이아웃에 Canvas을 사용해야하는 특별한 이유가 있습니까? 그렇지 않다면 수평 방향으로 StackPanel을 사용하는 것이 좋습니다. 그러면 레이아웃 계산이 처리됩니다.

+0

메신저는 각각의 항목이 실제로 캔버스에 절대적으로 개별적이어야하고 절대적으로 배치되어야한다는 것을 의미하는 스크롤링 된 마키 효과를 수행합니다. – Mark

+0

이제는 의미가 있습니다.) – xenry

4

당신은 항상에 위양을 첨부 할 수있는 PropertyMetatdata/OnValueChanged 무언가 0에서 ActualHeight/ActualWidth 변경, 당신의 스크롤을 조정하는 경우는 적어도 한 번 렌더링하면, ActualWidth/ActualHeight에 값이됩니다

LocalNewsControl() 
{ 
    var descriptor = DependencyPropertyDescriptor.FromProperty(ActualWidthProperty, typeof(TextBlock)); 
    if (descriptor != null) 
     descriptor.AddValueChanged(myTextBlock, ActualWidth_ValueChanged); 
} 

private void ActualWidth_ValueChanged(object a_sender, EventArgs a_e) 
{ 
    //Modify you scroll things here 
    ... 
} 
+0

그것은 어느 시점에서 편리 할 수있는 멋진 트릭입니다 :) –