2012-04-23 9 views
5

EDIT2: जब चार्ट पॉप्युलेट हो जाता है तो मैं अब मूल्यों को बदलने में असमर्थ हूं। यहां तक ​​कि जब मैं सूची में मानों को बदलता हूं (जहां आइटम नियंत्रण को मान प्राप्त होते हैं) चार्ट नए मानों के साथ अपडेट नहीं लगता है।डाटाबेसिंग आइटम कंट्रोल (डेटा टेम्पलेट) प्रोग्रामिंग पर मूल्यों को अपडेट नहीं करता है/केवल

मैं टाइमर में GetDataGrafiek() विधि को प्रत्येक एक्स सेकंड में अपना चार्ट अपडेट करने के लिए कॉल करता हूं।

 Grafiek graf = new Grafiek(); 
     graf.GetDataGrafiek(); 

इस वजह से थ्रेडिंग टाइमर एक अलग थ्रेड में चल (IsAsynchronousObjectDataProvider में विधि) या है मैं अपने टाइमर विधि में ItemsControl की DataContext का उपयोग करने की आवश्यकता है?

संपादित करें:

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])} 
     }; 
:
मैं चार्ट जब कार्यक्रम पहले से ही ऐसा चल रहा था मैं ObservableCollection<GrafiekBar> स्थिर (सूची है कि भरण और सलाखों के मूल्य रखती है) बनाया पॉप्युलेट करने में सक्षम में असमर्थ था और प्रारंभ निम्नलिखित के रूप में है

एमएसडीएन से: ऑब्जेक्टडाटाप्रोवाइडर: "हालांकि, यदि आप पहले से बनाए गए किसी ऑब्जेक्ट पर बाध्यकारी हैं, तो आपको निम्न उदाहरण के रूप में कोड में डेटाकॉन्टेक्स्ट सेट करना होगा।"


मैं एक ItemsControl है कि एक साधारण बार चार्ट के रूप में प्रदर्शित किया जा रहा है। जब मैं मानों को निर्दिष्ट करता हूं (मेरे कोड में हार्डकोड किया गया है) चार्ट सफलतापूर्वक पॉप्युलेट हो जाता है।

जो मैं करता हूं वह मूल रूप से सबसे बड़ा मूल्य 100% पर सेट कर रहा है और शेष सलाखों की लंबाई की गणना करता है।

समस्या: मैं नहीं चाहता कि चार्ट बार मान हार्डकोड किए गए हों लेकिन बार को रनटाइम बदलना होगा। इसके लिए मैं Threading.Timer का उपयोग करता हूं जो मेरा प्रोग्राम चलने तक हर सेकेंड चलता है (अन्य टाइमर भी इस टाइमर में होते हैं)।

चार्ट बार मान प्रत्येक x सेकंड में इस टाइमर के भीतर होने वाली गणनाओं के आधार पर अपडेट प्राप्त करते हैं।

मैंने सब कुछ करने की कोशिश की है और जब मेरा प्रोग्राम चल रहा है तो मुझे मूल्यों को प्रदर्शित नहीं किया जा सकता है। मैं केवल सलाखों को देख सकता हूं जब मैं उन्हें हार्डकोड करता हूं (थ्रेड के अंत में GetDataGrafiek() का क्षेत्र देखें)। मैं वास्तव में क्या गलत/लापता कर रहा हूँ?

GetDataGrafiek() (मेरे चार्ट को पॉप्युलेट करने की गणना) को ObjectDataProvider में बुलाया जाता है।

यह विधि टाइमस्पेन इनपुट के रूप में लेती है और फिर गणना करता है इसलिए मुझे डबल वैल्यू (ऊपर वर्णित 100% मूल्य के आधार पर) मिलता है जो तब बार के मान (= दिनांक की चौड़ाई) में रखा जाता है।मेरी ItemsControl के लिए

<ObjectDataProvider x:Key="odpLbGrafiek" ObjectType="{x:Type myClasses:GrafiekBar}" MethodName="GetDataGrafiek"/> 

DataTemplate (यह मेरा चार्ट की सलाखों के मूल्य के लिए चौड़ाई का उपयोग करता है)

<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() जब यह किया जाता है, तो क्षेत्र में हार्डकोडेड मान होते हैं मेरा चार्ट सफलतापूर्वक 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)); 
     } 
    } 
} 

थ्रेडिंग टाइमर हर दूसरे (कि गणना के तर्क और getDataGrafiek (है) के अपडेट के लिए जीयूआई धागा करने के लिए एक आह्वान वहाँ करता है कहा जाता है चलाता है।

private void MyTimerCallBack(object state) 
    { 
     DisplayWegingInfo(); 

     App.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, 
      new Action(() => 
      { 
       //actions that involve updating the UI 
       CaculateTimeBetweenWegingen(); 
      })); 
    } 

बेस्ट सादर पीटर।

+0

मुझे यकीन नहीं है कि मैं यहां क्या कर रहा हूं उसका पालन करता हूं, लेकिन टाइमर चलने से सुपर अजीब लगता है। क्या आप इसके बजाय घटनाओं का जवाब नहीं दे सकते? – Oliver

+0

उस टाइमर में प्रति सेकंड होने वाली गणनाओं के आधार पर चार्ट को बदलना है (या आवश्यक नहीं है)। मुझे सच में यकीन नहीं है कि इसे कैसे हल किया जाए। – PeterP

+0

बस एक मोटा अनुमान: क्या आपने सामान्य टाइमर के बजाय DispatcherTimer का उपयोग करने का प्रयास किया है। इस टाइमर को डब्ल्यूपीएफ को – SvenG

उत्तर

0

यह अंधेरे में एक शॉट है, क्योंकि मैंने आपके सभी कोडों को पढ़ा नहीं है, लेकिन यहां एक विचार है: आप एक स्थिर संसाधन के लिए बाध्यकारी हैं? यह एक बार पढ़ा जाता है और यह है, आह? इसके बजाए गतिशील संसाधन का प्रयास करें।

+0

आह, कोई बात नहीं, वह एक बेवकूफ विचार था। वास्तव में CaculateTimeBetweenWegingen() क्या करता है; कर? –

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 उपयोग कर रहे हैं।

+0

इसके अलावा, एक चीज जिसे मैं वास्तव में समझ में नहीं आया वह हैडलर का उद्देश्य क्या है। यदि आप सीधे डब्ल्यूपीएफ से बाध्यकारी हैं, तो आपको हैंडलर की आवश्यकता नहीं है, केवल XSML में डेटा बाध्य में UpdateSourceMethod = PropertyChanged। – William

संबंधित मुद्दे