EDIT2: Grafik dolduğunda artık değerleri değiştiremiyorum. Listedeki değerleri değiştirdiğimde (ItemControls değerlerini nereden alır), grafik yeni değerlerle güncellenmiyor gibi görünüyor.Databinding ItemsControl (DataTemplate) güncellenmiyor/program başlangıcındaki değerleri alıyor
Grafikimi her x saniyede bir güncellemek için zamanlayıcıda GetDataGrafiek() yöntemini çağırıyorum.
Grafiek graf = new Grafiek();
graf.GetDataGrafiek();
bunun nedeni Threading Timer ayrı bir konu çalıştıran (IsAsynchronous
ObjectDataProvider
yılında yöntemi) veya mı benim zamanlayıcı yönteminde ItemsControl DataContext
erişmek gerekir?
DÜZENLEME:
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])}
};
: ben program zaten bu yüzden koşuyordu ı
ObservableCollection<GrafiekBar>
statik (çubukların Doldur ve Değerini tutan listeyi) yapılan grafiği doldurmamız mümkün edemedi ve başlatıldı aşağıdaki gibidir
MSDN: ObjectDataProvider: "Ancak, önceden oluşturulmuş bir nesneye bağlanıyorsanız, aşağıdaki örnekte olduğu gibi, DataContext'i kod olarak ayarlamanız gerekir."
basit bir çubuk grafik olarak görüntülenen bir ItemsControl sahiptir. Değerlerimi atarken (codeBehind kodumda kodlanmış) grafik başarılı bir şekilde doldurulur.
Temel olarak, en büyük değeri% 100 olarak ayarlamak ve kalan çubukların kalan uzunluğunu hesaplamak.
Sorun: Grafik çubuğu değerlerinin kodlamasını istemiyorum ancak çubukların runTime değerini değiştirmek zorundayım. Bunun için programımın çalışmakta olduğu her saniye çalışan bir Threading.Timer
kullanın (diğer hesaplamalar bu zamanlayıcıda da olur).
Grafik çubuk değerleri, bu zamanlayıcıda gerçekleşen hesaplamalara göre her x saniyede bir güncelleme alır.
Her şeyi denedim ve programım çalışırken değerleri gösteremiyorum. Sadece barkodlarını okuduğumda çubukları görebilirim (iş parçasının sonunda GetDataGrafiek()
bölgesine bakın). Tam olarak ne yanlış/eksik yapıyorum?
GetDataGrafiek()
(grafiğimi doldurmak için hesaplamalar), ObjectDataProvider
numaralı telefondan çağrılır.
Bu yöntem, girdi olarak TimeSpan'ı alır ve daha sonra hesaplamalar yapar, böylece bir Double Value (yukarıda açıklanan% 100 değerine dayanarak) elde edersiniz, bu da çubuğun Değerine yerleştirilir (= dateTemplate genişliği).Benim ItemsControl için
<ObjectDataProvider x:Key="odpLbGrafiek" ObjectType="{x:Type myClasses:GrafiekBar}" MethodName="GetDataGrafiek"/>
DataTemplate (bu Haritamda çubuklarının değeri genişliği kullanır)
<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:
<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() Bölge bittiğinde, bölge kodlanmış değerleri tutar grafiğimde 6 çubuk başarıyla görüntülenir. Bölgeye yorum yaptığımda artık herhangi bir görünür çubuk almıyorum.
Bu yöntem, Double
değerleriyle bir liste döndürür. Her değer, DataTemplate
'da Genişlik olarak temsil edilen bir çubuğu temsil eder ve Dolgu sadece belirli bir renk verir.
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));
}
}
}
güncellemeler için GUI evreye bir çağırmak orada yapar denilen (yani hesaplama mantığını ve getDataGrafiek (vardır) her saniye çalışır Threading zamanlayıcısı.
private void MyTimerCallBack(object state)
{
DisplayWegingInfo();
App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(() =>
{
//actions that involve updating the UI
CaculateTimeBetweenWegingen();
}));
}
Saygılarımızla Peter.
Burada ne yaptığınızı takip ettiğimden emin değilim, ancak bir zamanlayıcıya sahip olmak çok tuhaf geliyor. Bunun yerine etkinliklere cevap veremez misin? – Oliver
Grafik, o zamanlayıcıda her saniyede gerçekleşen hesaplamalara bağlı olarak değişmeli (veya gerekli değilse değiştirilmemelidir). Bunu nasıl çözeceğime gerçekten emin değilim. – PeterP
Sadece kaba bir tahmin: Normal bir Zamanlayıcı yerine DispatcherTimer kullanmayı denediniz mi? Bu zamanlayıcı, WPF'nin – SvenG