그룹 상자에 텍스트 블록을 추가하고 그래프 컨트롤에 데이터가로드 될 때 확인해야합니다.
문제
그래프 컨트롤을 만들고 있습니다. X와 Y Axis Tall 라벨을 추가하기 위해 내가하고있는 일은 각 집계에 텍스트 블록을 추가하고 해당 탈리 마크와 관련된 값을 보여주는 것입니다.
그러나 데이터를로드하고 데이터베이스를로드하고 Textbolcks를 다시로드하고 그래프 영역을 새로 고침 해야하는 경우 그래프 창에있는 이전 텍스트 블록을 제거 할 수 없습니다.
이 문제를 극복하기 위해 텍스트 블록을 측면에 그룹 상자에 넣고 그래프 창을 다시 작성하여 그룹 상자 요소를 삭제하고 다시 넣을 때 ..
이 접근법이 정확합니까? 클래스 뒤에 코드에 요소를 GroupBox에 넣는 방법을 알려주세요. 그리고 그들이 내 문제에 대한 다른 해결책인지 알려주세요.
안부, Rangana.
해결책
WPF에는 대부분의 문제에 대한 많은 해결책이 있습니다. 나는 당신의 문제에 대한 세 가지 가능한 해결책, 즉 당신이 묘사 한 것과 다른 두 가지 해결책에 대해 논의 할 것입니다. 당신에게 가장 적합한 사람을 결정할 수 있습니다.
솔루션 1 : 텍스트 블록 객체를 사용하여 레이블을 멸망시킵니다.
당신이있는 것 같네요 Canvas
그리고 당신은 추가하고 있습니다 TextBlock
각 진드기 마크에 대해. 성능이 너무 중요하지 않고 데이터 바인딩을 사용할 수없는 경우 이것은 실행 가능한 솔루션입니다.
이 경우 텍스트 블록을 제거하는 두 가지 방법이 있습니다.
당신은 보관할 수 있습니다
List<TextBlock>
마지막으로 레이블을 만든 텍스트 블록의 모든 텍스트 블록 목록이 포함되어 있습니다. 레이블을 재현 할 때 마다이 목록을 통해 실행하고 포함 된 패널 (캔버스)에서 목록의 각 텍스트 블록을 제거하십시오.새 캔버스를 생성하고 텍스트 블록을 넣은 다음 relabel시 전체 캔버스를 삭제할 수 있습니다.
다음은 두 번째 기술의 예입니다. 약간 더 효율적이기 때문입니다.
class MyGraphBuilder
{
Canvas _labelCanvas;
...
void AddLabels()
{
// Remove old label canvas, if any
if(_labelCanvas!=null)
_graphCanvas.Children.Remove(_labelCanvas);
// Add new label canvas
_labelCanvas = new Canvas();
_graphCanvas.Children.Add(_labelCanvas);
// Create labels
foreach(...)
{
...
_labelCanvas.Add(new TextBlock ...
}
...
}
}
해결책 2 : 데이터 바인딩 사용
WPF에서는 한 줄의 코드를 작성하지 않고도 많은 그래프를 만들 수 있습니다! WPF의 내장 데이터 바인딩은 비교적 복잡한 막대 차트 등을 생성하기에 충분합니다.
다음은 간단한 막대 차트를 만들기 위해 데이터 바인딩을 사용하는 예입니다.
<ItemsControl ItemsSource="{Binding myData}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel>
<TextBlock Width="50" Text="{Binding Label}"/>
<Rectangle VerticalAlignment="{Stretch}" Width="{Binding Value}">
<Rectangle.LayoutTransform>
<ScaleTransform ScaleX="10" /> <!-- Scale factor here, can be binding too -->
</Rectangle.LayoutTransform>
</Rectangle>
<TextBlock Text="{Binding Value}" FontSize="8"/>
</DockPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
숫자 라벨은 수평으로 배치 된 두 번째 Itemscontrol을 사용하여 수평 축에 추가 할 수 있으며, 데이터 템플릿으로 고정 너비를 표시하고 숫자와 점령 표시를 표시합니다.
해결책 3 : 저수준 드로잉 클래스 사용
a를 구성하여 그래프를 작성하십시오 DrawingGroup
물체와 추가 GeometryDrawing
그리고 GlyphRunDrawing
그것에 물체를 넣고, 다음을 넣습니다 DrawingGroup
내부에 DrawingVisual
그리고 당신의 메인에 추가하십시오 Panel
.
하나를 사용해야합니다 GeometryDrawing
또는 GlyphRunDrawing
주어진 브러시와 펜을 공유하는 각 항목 세트에 대해. 예를 들어 축과 스타크가 모두 같은 색상과 너비 인 경우 단일을 만듭니다. GeometryDrawing
그들 모두에 대해, 그러나 각 스타크 마크가 다른 색상이라면, 여러 가지를 만들어 GeometryDrawing
사물.
당신은 a를 만들 것입니다 Geometry
각각의 개체 GeometryDrawing
. 최상의 효율성을 위해서는 다음과 같습니다 StreamGeometry
, 그러나 다른 형상 클래스도 잘 작동하고 사용하기 쉽고 XAML에서 초기화 될 수 있습니다. 생성 a PathGeometry
또는 EllipseGeometry
아마도 이미 당신에게 유사 할 것입니다. StreamGeometry
. 당신은 전화를 통해 이것을합니다 Open
a using()
진술, 그리고 반환 된 컨텍스트에 편지를 씁니다. 예는 다음과 같습니다.
Geometry BuildAxesAndTicksGeometry()
{
// First create geometry
var geometry = new StreamGeometry();
using(var context = geometry.Open())
{
// Horizontal axis
context.BeginFigure(new Point(0,0), false, false);
context.LineTo(new Point(_width, 0), true, false);
// Vertical axis
context.BeginFigure(new Point(0,0), false, false);
context.LineTo(new Point(0, _height), true, false);
// Horizontal ticks
for(int i=0; i<_nTicksHorizontal; i++)
{
context.BeginFiture(new Point(i * _tickSpacing, -10), false, false);
context.LineTo(new Point(i * _tickSpacing, 10), true, false);
}
// Do same for vertical ticks
}
// Now add it to a drawing
return new GeometryDrawing { Geometry = geometry, Stroke = _axisPen };
}
Drawing BuildDrawing()
{
var mainDrawing = new DrawingGroup();
mainDrawing.Add(BuildAxesAndTicksGeometry());
... // Add other drawings, including one or more for the data
return mainDrawing;
}
void UpdateDrawing()
{
myDrawingVisual.Drawing = BuildDrawing(); // where myDrawingVisual is defined in the XAML
}
솔루션 비교
대부분의 경우 솔루션 2 또는 3을 권장합니다.
- 그래프가 데이터 바인딩을 사용하기에 충분히 간단하면 많은 시간을 절약 할 수 있습니다. 솔루션 2와 함께 이동하십시오.
- 데이터 바인딩으로 그래프를 수행 할 수없는 경우 드로잉 객체를 사용하는 것은 다른 기술만큼이나 간단하며 더 잘 수행 할 수 있습니다. 솔루션 3으로 이동하십시오.
귀하의 경우에 이미 솔루션 1에 상당한 작업을 투자 한 경우, 아마도 최고가 아니더라도 그것을 고수하고 싶을 수도 있습니다.