EDIT2:グラフにデータが入力されると、値を変更できなくなります。リスト (ItemControls が値を取得する場所) の値を変更しても、チャートは新しい値で更新されないようです。
タイマーで GetDataGrafiek() メソッドを呼び出して、x 秒ごとにグラフを更新します。
Grafiek graf = new Grafiek();
graf.GetDataGrafiek();
これは、Threading Timer が別のスレッド (IsAsynchronous
のメソッド) で実行されているためですか、それともタイマー メソッドで ItemsControl にObjectDataProvider
アクセスする必要がありますか?DataContext
編集:プログラムが既に実行されているときにチャートにデータを入力できなかったので、ObservableCollection<GrafiekBar>
静的 (バーの塗りつぶしと値を保持するリスト) を作成し、初期化したのは次のとおりです。
public static ObservableCollection<GrafiekBar> listGrafiek = new ObservableCollection<GrafiekBar>()
{
new GrafiekBar() {Value = 0, Fill = (Brush)convertor.ConvertFromString(kleuren[0])},
new GrafiekBar() {Value = 0, Fill = (Brush)convertor.ConvertFromString(kleuren[1])},
new GrafiekBar() {Value = 0, Fill = (Brush)convertor.ConvertFromString(kleuren[2])}
};
MSDN から: ObjectDataProvider: "ただし、既に作成されているオブジェクトにバインドする場合は、次の例のように、コードで DataContext を設定する必要があります。"
シンプルな棒グラフとして表示されている ItemsControl があります。値を割り当てると ( codeBehind にハードコードされています)、グラフに正常にデータが取り込まれます。
私がしていることは、基本的に最大値を 100% に設定し、残りのバーの長さを計算することです。
問題:
チャート バーの値をハードコーディングしたくありませんが、バーは runTime を変更する必要があります。このために、プログラムが実行されている限り毎秒実行される aThreading.Timer
を使用します (このタイマーでは他の計算も行われます)。
チャート バーの値は、x 秒ごとにこのタイマー内で行われる計算に基づいて更新されます。
すべてを試しましたが、プログラムの実行中に値が表示されません。バーをハードコーディングした場合にのみバーが表示されます (GetDataGrafiek()
スレッドの最後にある領域を参照してください)。私は正確に何を間違っている/行方不明ですか?
GetDataGrafiek()
(グラフに入力するための 計算) は で呼び出されますObjectDataProvider
。
このメソッドは TimeSpan を入力として受け取り、計算を実行するため、(上記で説明した 100% 値に基づいて) Double 値を取得し、バーの値 (= dateTemplate の幅) に配置されます。
<ObjectDataProvider x:Key="odpLbGrafiek" ObjectType="{x:Type myClasses:GrafiekBar}" MethodName="GetDataGrafiek"/>
私の ItemsControl の DataTemplate (これは私のグラフのバーの値に Width を使用します)
<DataTemplate x:Key="GrafiekItemTemplate">
<Border Width="Auto" Height="Auto">
<Grid>
<Rectangle StrokeThickness="0" Height="30"
Margin="15"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Width="{Binding Value}"
Fill="{Binding Fill}">
<Rectangle.LayoutTransform>
<ScaleTransform ScaleX="20" />
</Rectangle.LayoutTransform>
</Rectangle>
</Grid>
</Border>
</DataTemplate>
アイテムコントロール:
<ItemsControl x:Name="icGrafiek"
Margin="50,3,0,0"
ItemsSource="{Binding Source={StaticResource odpLbGrafiek}}"
ItemTemplate="{DynamicResource GrafiekItemTemplate}"
RenderTransformOrigin="1,0.5" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.RowSpan="6">
<ItemsControl.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="-1" ScaleX="1"/>
<SkewTransform AngleY="0" AngleX="0"/>
<RotateTransform Angle="180"/>
<TranslateTransform/>
</TransformGroup>
</ItemsControl.RenderTransform>
</ItemsControl>
GetDataGrafiek()リージョンにはハードコーディングされた値が保持されます。これが完了すると、チャートに 6 本のバーが正常に表示されます。地域にコメントすると、目に見えるバーが表示されなくなりました。
このメソッドは、Double
値を含むリストを返します。各値は、 で幅として表されるバーを表しDataTemplate
、塗りつぶしはそれに特定の色を与えます。
ObservableCollection<GrafiekBar> listGrafiek = new ObservableCollection<GrafiekBar>();
public ObservableCollection<GrafiekBar> GetDataGrafiek()
{
var converter = new System.Windows.Media.BrushConverter();
#region ***TEST HARDCODED BAR VALUES***
int[] testWaardenUren = new int[] { 2, 1, 0, 1, 2, 0 };
int[] testWaardenMinuten = new int[] { 58, 2, 55, 55, 2, 20 };
for (int j = 0; j < 6; j++)
{
TimeSpan ts = new TimeSpan(testWaardenUren[j], testWaardenMinuten[j], 0);
GlobalObservableCol.regStilstanden[j].Value = ts;
GlobalObservableCol.regStilstanden[j].Name = "";
}
#endregion
totalMinutesMaxValue = GetLargestValueStilstanden(); //= "100%" value
//calculate % of stilstanden Values
for (int i = 0; i < GlobalObservableCol.regStilstanden.Count; i++)
{
Double totalMin = GlobalObservableCol.regStilstanden[i].Value.TotalMinutes;
totalMin = totalMin / totalMinutesMaxValue * 10;
valuesChartPercentage.Add(totalMin);
}
//the barChart (itemsControl) gets its final values here
for (int j = 0; j < GlobalObservableCol.regStilstanden.Count; j++)
{
GrafiekBar bar = new GrafiekBar();
bar.Value = valuesChartPercentage[j];
bar.Fill = converter.ConvertFromString(kleuren[j]) as Brush;
listGrafiek.Add(bar);
}
return listGrafiek;
}
GrafiekBar.cls
public class GrafiekBar : INotifyPropertyChanged
{
private double value;
private Brush fill;
public GrafiekBar()
{
}
public double Value
{
get { return this.value; }
set
{
this.value = value;
NotifyPropertyChanged("Value");
}
}
public Brush Fill
{
get { return this.fill; }
set
{
this.fill = value;
NotifyPropertyChanged("Fill");
}
}
//interface INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
//interface INotifyPropertyChanged
private void NotifyPropertyChanged(String info)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
毎秒実行される Threading タイマー (計算ロジックとそこで呼び出される getDataGrafiek() を持ち、更新のために GUI スレッドを呼び出します。
private void MyTimerCallBack(object state)
{
DisplayWegingInfo();
App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() =>
{
//actions that involve updating the UI
CaculateTimeBetweenWegingen();
}));
}
よろしくピーター。