私は2つのObservableCollection < TimeValue>を持つクラスを持っています。ここで、TimeValueは(INotifyPropertyChangedを介して)変更通知付きのカスタムDateTime/Valueペアです。私はこれらの目標と実績と呼ぶ。WPF DataGrid - MultiBindingでTimeSeriesを組み合わせると、変更通知が失われます。どうして?
これらをグラフにバインドすると、すべてが正常に動作し、2つのLineSeriesが得られます。私がDataGridにバインドすると、 "Date"の列と "Value"の列が正しく動作します。私は必要なTwoWayバインディングを取得することさえできます。
ただし、「日付」列を持つDataGridと、それぞれの対象と実際の列が必要です。問題は、範囲内のすべての日付をリストする必要があるのに対して、これらの日付の一部はターゲット、実績、またはその両方に対応する値を持たない可能性があることです。
したがって、ターゲットと実績を入力とし、いずれかのオリジナルが値を持たない場合はいつでも、null値を組み合わせたTimeSeriesCを出力するマルチバインディングを行うことにしました。
これは機能しますが、基礎となるデータの変更には反応しません。
これは、(1つのObservableCollectionに結合する)正常に動作します:
<ctrls:DataGrid Grid.Row="1" Height="400" AutoGenerateColumns="False" CanUserDeleteRows="False" SelectionUnit="Cell">
<ctrls:DataGrid.ItemsSource>
<Binding Path="Targets"/>
<!--<MultiBinding Converter="{StaticResource TargetActualListConverter}">
<Binding Path="Targets"/>
<Binding Path="Actuals"/>
</MultiBinding>-->
</ctrls:DataGrid.ItemsSource>
<ctrls:DataGrid.Columns>
<ctrls:DataGridTextColumn Header="Date" Binding="{Binding Date,StringFormat={}{0:ddd, MMM d}}"/>
<ctrls:DataGridTextColumn Header="Target" Binding="{Binding Value}"/>
<!--<ctrls:DataGridTextColumn Header="Target" Binding="{Binding Value[0]}"/>
<ctrls:DataGridTextColumn Header="Actual" Binding="{Binding Value[1]}"/>-->
</ctrls:DataGrid.Columns>
これは動作しますが、最初に初期化する場合にのみ。通知を変更する応答:
<ctrls:DataGrid Grid.Row="1" Height="400" AutoGenerateColumns="False" CanUserDeleteRows="False" SelectionUnit="Cell">
<ctrls:DataGrid.ItemsSource>
<!--<Binding Path="Targets"/>-->
<MultiBinding Converter="{StaticResource TargetActualListConverter}">
<Binding Path="Targets"/>
<Binding Path="Actuals"/>
</MultiBinding>
</ctrls:DataGrid.ItemsSource>
<ctrls:DataGrid.Columns>
<ctrls:DataGridTextColumn Header="Date" Binding="{Binding Date,StringFormat={}{0:ddd, MMM d}}"/>
<!--<ctrls:DataGridTextColumn Header="Target" Binding="{Binding Value}"/>-->
<ctrls:DataGridTextColumn Header="Target" Binding="{Binding Value[0]}"/>
<ctrls:DataGridTextColumn Header="Actual" Binding="{Binding Value[1]}"/>
</ctrls:DataGrid.Columns>
そして、ここでは私のIMultiValueConverterである:それは値を表示するので
class TargetActualListConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
TimeSeries<double> Targets = values[0] as TimeSeries<double>;
TimeSeries<double> Actuals = values[1] as TimeSeries<double>;
DateTime[] range = TimeSeries<double>.GetDateRange(Targets, Actuals);//Get min and max Dates
int count = (range[1] - range[0]).Days;//total number of days
DateTime currDate = new DateTime();
TimeSeries<double?[]> combined = new TimeSeries<double?[]>();
for (int i = 0; i < count; i++)
{
currDate = range[0].AddDays(i);
double?[] vals = { Targets.Dates.Contains(currDate) ? (double?)Targets.GetValueByDate(currDate) : null, Actuals.Dates.Contains(currDate) ? (double?)Actuals.GetValueByDate(currDate) : null };
combined.Add(new TimeValue<double?[]>(currDate, vals));
}
return combined;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
TimeSeries<double?[]> combined = value as TimeSeries<double?[]>;
TimeSeries<double> Targets = new TimeSeries<double>();
TimeSeries<double> Actuals = new TimeSeries<double>();
foreach (TimeValue<double?[]> tv in combined)
{
if(tv.Value[0]!=null)
Targets.Add(new TimeValue<double>(tv.Date,(double)tv.Value[0]));
if (tv.Value[1] != null)
Actuals.Add(new TimeValue<double>(tv.Date, (double)tv.Value[1]));
}
TimeSeries<double>[] result = { Targets, Actuals };
return result;
}
}
私は、あまりにも遠くなることはできません。
私は間違っていますか? または、これを行う簡単な方法がありますか?
ありがとうございます!
おかげでrmoore。残念ながら、私が持っているセットアップは、CollectionChangedイベントに応答しません。私はCompositeCollectionsを試しましたが、表示したいコレクションは2つの入力と同じサイズではないので、どのように動作させるのか分かりません。奇妙なことに、Convertメソッドは最初の表示で1回だけ(値ごとに)呼び出され、再び表示されません。 – AdrianoFerrari
その場合、もっと知ることなくこれを解決する最も簡単な方法は、TargetやActualをマージすることができる何らかの種類のラッパークラスを作成することです。次に、これらのラッパーのObservableCollectionを1つ作成すると、バインドするほうがずっと簡単になります。 – rmoore
私はそうする必要があると思います。私が意図したようにすることができれば、私はここに戻ってきます。なぜなら、それはより簡単だったからです。 ありがとうございましたrmoore。これと答えて、あなたにポイントを与えてもらえますか? – AdrianoFerrari