5

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();
            }));
    }

よろしくピーター。

4

2 に答える 2

0

私はあなたのコードをすべて読んだわけではありませんが、ここに考えがあります: あなたは静的リソースにバインドしていますよね? 一度読まれて、これで終わりですよね?代わりに DynamicResource を試してください。

于 2012-05-02T21:54:31.770 に答える
0

別のスレッドから次のコードにアクセスしている場合、問題が発生します。

private void NotifyPropertyChanged(String info)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}

他のスレッドがイベントを発生させるため、ディスパッチャ スレッド (イベントにサブスクライブしている場合) がエラーになります。

代わりに試す

private void NotifyPropertyChanged(String info)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (PropertyChanged != null)
    {
        if (System.Threading.Thread.CurrentThread == System.Windows.Application.Current.Dispatcher.Thread)
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        else
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => PropertyChanged(this,new PropertyChangedEventArgs(info));
    }
}

また、WPF で UpdateSourceMethod=PropertyChanged を使用していることを確認してください。

于 2012-12-14T01:11:26.300 に答える