이 질문은 대중적인 질문이지만 정확하게 대답 한 항목을 찾을 수는 없었지만 내 검색에서 뭔가를 놓친 경우 사과드립니다. 내가 만들고 다음 코드를 사용하여 런타임에 컨트롤을 측정하기 위해 노력하고있어WPF에서 런타임에 생성되는 측정 컨트롤
(측정은 스타일을 움직이는하기 위해 컨트롤을 스크롤 사용됩니다 - 각 컨트롤은 서로 다른 크기) :
Label lb = new Label();
lb.DataContext= task;
Style style = (Style)FindResource("taskStyle");
lb.Style = style;
cnvMain.Children.Insert(0,lb);
width = lb.RenderSize.Width;
width = lb.ActualWidth;
width = lb.Width;
코드는 Label 컨트롤을 만들고 스타일을 적용합니다. 스타일에는 개체 "작업"에 바인딩되는 제어 템플릿이 포함되어 있습니다.
lb.Width = NaN
lb.RenderSize.Width = 0
lb.ActualWidth = 0
가 어떤이다 : 나는 항목을 만들 때 나는 다음과 같은 결과를 (내가 단계별로 차례로 각 속성을 검사) 얻을 위에 나는 속성 중 하나를 사용하여 컨트롤을 측정하려고 그러나 때, 완벽하게 나타납니다 런타임에 생성하는 컨트롤의 렌더링 된 높이와 너비를 가져 오는 방법은 무엇입니까?
UPDATE : 답변으로 솔루션을 선택 해제를위한
죄송합니다. 그것들은 내가 설정 한 기본 예제 시스템에서 작동하지만, 내 완벽한 솔루션으로는 보이지 않습니다.
스타일과 관련이있을 수 있으므로 혼란스러워서 미안하지만 여기 모든 것을 붙여 넣습니다.
첫째, 자원 :
<Storyboard x:Key="mouseOverGlowLeave">
<DoubleAnimation From="8" To="0" Duration="0:0:1" BeginTime="0:0:2" Storyboard.TargetProperty="GlowSize" Storyboard.TargetName="Glow"/>
</Storyboard>
<Storyboard x:Key="mouseOverTextLeave">
<ColorAnimation From="{StaticResource buttonLitColour}" To="Gray" Duration="0:0:3" Storyboard.TargetProperty="Color" Storyboard.TargetName="ForeColour"/>
</Storyboard>
<Color x:Key="buttonLitColour" R="30" G="144" B="255" A="255" />
<Storyboard x:Key="mouseOverText">
<ColorAnimation From="Gray" To="{StaticResource buttonLitColour}" Duration="0:0:1" Storyboard.TargetProperty="Color" Storyboard.TargetName="ForeColour"/>
</Storyboard>
그리고 스타일 자체 :
<Style x:Key="taskStyle" TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Canvas x:Name="cnvCanvas">
<Border Margin="4" BorderBrush="Black" BorderThickness="3" CornerRadius="16">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="1" Color="SteelBlue"/>
<GradientStop Offset="0" Color="dodgerBlue"/>
</LinearGradientBrush>
</Border.Background>
<DockPanel Margin="8">
<DockPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="corbel"/>
<Setter Property="FontSize" Value="40"/>
</Style>
</DockPanel.Resources>
<TextBlock VerticalAlignment="Center" Margin="4" Text="{Binding Path=Priority}"/>
<DockPanel DockPanel.Dock="Bottom">
<Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4">
<TextBlock Margin="4" DockPanel.Dock="Right" Text="{Binding Path=Estimate}"/>
</Border>
<Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4">
<TextBlock Margin="4" DockPanel.Dock="Left" Text="{Binding Path=Due}"/>
</Border>
</DockPanel>
<DockPanel DockPanel.Dock="Top">
<Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4">
<TextBlock Margin="4" Foreground="LightGray" DockPanel.Dock="Left" Text="{Binding Path=List}"/>
</Border>
<Border Margin="4" BorderBrush="SteelBlue" BorderThickness="1" CornerRadius="4">
<TextBlock Margin="4" Foreground="White" DockPanel.Dock="Left" Text="{Binding Path=Name}"/>
</Border>
</DockPanel>
</DockPanel>
</Border>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
또한, 코드는 내가 사용 :
Label lb = new Label(); //the element I'm styling and adding
lb.DataContext= task; //set the data context to a custom class
Style style = (Style)FindResource("taskStyle"); //find the above style
lb.Style = style;
cnvMain.Children.Insert(0,lb); //add the style to my canvas at the top, so other overlays work
lb.UpdateLayout(); //attempt a full layout update - didn't work
Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>
{
//Synchronize on control rendering
double width = lb.RenderSize.Width;
width = lb.ActualWidth;
width = lb.Width;
})); //this didn't work either
lb.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); //nor did this
double testHeight = lb.DesiredSize.Height;
double testWidth = lb.RenderSize.Width; //nor did this
width2 = lb.ActualWidth; //or this
width2 = lb.Width; //or this
//positioning for my marquee code - position off-screen to start with
Canvas.SetTop(lb, 20);
Canvas.SetTop(lb, -999);
//tried it here too, still didn't work
lb.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
testHeight = lb.DesiredSize.Height;
//add my newly-created label to a list which I access later to operate the marquee
taskElements.AddLast(lb);
//still didn't work
lb.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
testHeight = lb.DesiredSize.Height;
//tried a mass-measure to see if that would work - it didn't
foreach (UIElement element in taskElements)
{
element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
}
의 때마다 그 값은 0으로 반환됩니다. 또는 숫자가 아니지만 레이블이 렌더링 될 때 크기가 명확하게 표시됩니다. 라벨이 화면에 표시 될 때 버튼 누름에서이 코드를 실행 해 보았지만 동일한 결과가 나타납니다.
내가 사용하고있는 스타일 때문입니까? 데이터 바인딩은 아마도? 내가 뭘 잘못 blindingly 명백한하거나 그냥 WPF Gremlins 할 정말 날 싫어하나요?
두 번째 업데이트 : 그 측정을 (발견했습니다
더 검색 후에는)은 원래 요소 크기에 적용됩니다. 컨트롤 템플릿이 실제로 컨트롤을 추가하여이를 수정하면 가장 좋은 방법은 아마도 각각을 측정하는 것이지만, 나는 그것이 조금 이상하다는 것을 인정합니다.
컴파일러에는 스택 패널과 같이 항목을 배치 할 때 사용해야하는 컨트롤의 모든 내용을 측정하는 방법이 있어야합니다. 접근 할 수있는 방법이 있어야하지만, 지금은 완전히 아이디어가 없습니다.
이 코드를 어디에서 실행하고 있습니까? 창 생성자에서? 그렇다면 컨트롤이 렌더링 될 때까지 기다려야합니다. – Carlo