2012-04-18 57 views
0

編輯:添加代碼ItemsControl的條形圖縮放

而且由於DateTime是否是不是真的日期時間(在HH字符串:mm:ss格式),我決定只使用字符串來代替,而時間跨度檢索總分鐘。

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

    <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> 

填充實際上給出了條形圖的條形的大小iself。

ItemsControl的:

<ItemsControl x:Name="icGrafiek" 
      Margin="20,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> 

下面的方法被調用的數據綁定。在那裏bar.Value給出了數據模板中的寬度值的值,它給出了一個條的大小。

public ObservableCollection<GrafiekBar> GetDataGrafiek() 
    { 
     var converter = new System.Windows.Media.BrushConverter(); 

     Double maxValueStilstanden = GetLargestValueStilstanden(); 

     TimeSpan tsMaxValue = TimeSpan.Parse(maxValueStilstanden.ToString()); 
     totalMinutesMaxValue = tsMaxValue.TotalMinutes; 

     //calculate % of stilstanden Values 
     foreach(String t in stilStandenList) 
     { 
      TimeSpan ts = TimeSpan.Parse(t); 
      Double totalMin = ts.TotalMinutes; 

      totalMin = totalMin/totalMinutesMaxValue * 100; 

      valuesChartPercentage.Add(totalMin); 
     } 

     for (int j = 0; j < valuesChartPercentage.Count; j++) 
     { 
      GrafiekBar bar = new GrafiekBar(); 
      bar.Value = valuesChartPercentage[j]; 
      bar.Fill = converter.ConvertFromString(kleuren[j]) as Brush; 
      listGrafiek.Add(bar); 
     } 

     return listGrafiek; 
    } 

另一個問題實際上是寬度(酒吧的大小)。我實際上必須做* 10000才能看到酒吧本身。


我使用的是ItemsControl的是風格,所以它看起來像一個條形圖。

因此,例如,具有從1到5的5個值的數組創建5個具有不同條形尺寸和每個不同顏色的條形。 相像以下示例http://www.c-sharpcorner.com/uploadfile/mahesh/bar-chart-in-wpf/

問題:

我的問題是與杆的規模大小(在這種情況下,width屬性,因此需要INT /雙值)。

  • 我的程序在HH記錄幾個DateTime是否:mm:ss格式
  • 的酒吧應該在這些日期時間進行縮放

例如,我可以有一個酒吧,1時22分11秒或00:01:11,最高金額爲6.

將這些DateTime值縮放到某個double值的最佳方法是什麼? 該值將用於給出圖表上的小節大小。

猜猜我在尋找某種計算方式,它可以計算出所有我的數值,所以我不會突然得到一個非常大的值,並且不會出現在我的用戶界面中。

最乾淨的解決方案將是所有酒吧相互比較,當一個改變另一個增長/縮小,但這並不是必需的,除非它不像它聽起來那麼複雜。

酒吧本身並不需要過於精確,它只是爲了瞭解情況的一般情況。確切的值將寫入數據庫。

任何建議都非常歡迎!

謝謝PeterP。

回答

1

我會選擇一個基準日,並讓您的收藏圖的基準日數據日期之間的天/小時/分鐘數

你甚至可以做到這一點使用轉換器,在此將基準日期作爲轉換器參數傳遞。

你的兩個示例日期(01:22:1100:01:11)實際上倍,所以在這種情況下,我剛剛繪製因爲0的分鐘數,因此實際數據值曲線圖將是82和1

在對你的編輯詢問縮放的反應,你會以百分比形式表示一切。在這種情況下,請取最大的數字,並根據最大數量的百分比繪製每隔一個數字的圖形。

因此,使用您的兩個示例時間,我將它們轉換爲數字82和1,將較大數字(82)作爲100%,並返回一個包含每個數字的百分比爲82的列表,名單將包含100%和1.2%(1/82)。

你仍然可以做到這一點無論是在ViewModelItemsSource轉換(轉換器將需要整個列表作爲參數,並返回整個列表返回值)


編輯

爲迴應您的意見,下面是我將如何使用對ItemsSource進行設置。一個轉換器只需要一個數據值,並將其轉換爲另一個僅用於顯示用戶界面的值。

最初的XAML應該是這樣的:

<ItemsControl ItemsSource="{Binding MyCollection, 
    Converter="{StaticResource MyTimeConverter}}" /> 

其中MyCollectionObservableCollection<DateTime>,並且MyTimeConverter執行以下操作:

  1. 鑄傳遞valueObservableCollection<DateTime>,因爲所有的轉換參數通過爲object
  2. 循環收集並找出最大的時間e
  3. 以集合中最大的時間,並找出它有多少分鐘。這將是你100%的值,你將基地所有其他時間關閉的,所以存儲在變量
  4. 你最大的時間有多少分鐘的返回值
  5. 循環遍歷開始收集創建一個新的List<decimal>。對於收集中的每一次,將它除以在步驟3中存儲的「100%值」,這將給出該條應該與最大值相比多長時間的百分比。將此百分比加到回報中List<decimal>
  6. 返回List<decimal>ItemsControl。這List<decimal>將被用作ItemsSource而不是實際ObservableCollection<DateTime>

這意味着你的ItemsControl現在綁定到小數的集合,其中一個值是100%,並會採取屏幕的全寬,全其他值被縮放到最大值。

關於使用計時器更新集合的問題,您的計時器應更新,即ItemsControl所綁定的名爲MyCollection。定時器根本不知道或關心轉換器代碼。例如,如果您的計時器想要重新創建MyCollection一整套新的時間,那麼它可以,並且UI將自動重新運行轉換器代碼並更新條形圖,因爲ObservableCollections會告訴UI當集合發生變化並且UI需要更新時。

至於我在下面的評論中提到的「基準日期」,如果您繪製的是一組日期而不是時間,那麼您需要一個基準日期,以便您的圖形不會延伸回1/1/0001。您不希望使用最短日期,因爲這會導致您的最低值在條形圖中顯示爲0,因此您將通過Converter特定日期作爲圖形中的起點。如果基準日期是1/1/12,而最大日期是3/1/12,那麼您的圖表將從2012年1月1日延伸至2012年3月1日。

基準日期將在轉換器的步驟3和5中使用。例如,您可以獲取基準日期和數據日期之間的天數,而不是獲取該時間的分鐘數。

您也可以計算轉換器中的基準日期,例如最低日期之前的10天,儘管這可能會使圖形偏斜超過您的偏好,具體取決於數據。

+0

感謝您的回覆,是否可以說明代碼中的一部分?我的程序運行一個計時器,它的值可能每5秒更新一次。幾秒鐘的時間也是可能的。 – PeterP 2012-04-18 14:27:09

+1

@PeterP我會使用'ItemsSource'轉換器,它需要一個'ObservableCollection ',以及一個基準日期時間參數。在轉換器中,我將從循環列表開始,找到最大日期。以基準日期和最大日期之間的分鐘數/天/小時數/秒爲單位,並將其存儲在某個地方作爲100%使用。現在創建一個新列表來保存你的返回值。循環顯示原始列表,獲取該日期和基準日期之間的分鐘數/天/小時/秒數,並將其除以100%數,然後將結果添加到返回列表中。返回新列表到IC – Rachel 2012-04-18 14:57:58

+1

@PeterP如果您使用'ObservableCollection '而不是'List ',計時器將不會成爲問題,因爲ObservableCollection會響應計時器可觸發的更改通知。 – Rachel 2012-04-18 14:58:50

0

這聽起來像你只需要跟蹤所有值的最大值。然後,根據這個最大規模的每個值:

var scale = value/maximum; 
var height = scale * ActualHeight; 

當然,你居然設置每個項目的高度很可能會通過結合的方式。

0

恕我直言,你的整個條形圖應該在後面有一個ViewModel,這個VM有計算最大值然後定義縮放的邏輯。

1

標準化。

  • 將總時間轉換爲秒。
  • (除以總時間總的可用寬度)= factorA
  • 找到每個條的適當的寬度,通過factorA
  • 乘以其時間

編輯:選擇一個合適的日期/時間來測量從零,或者你可以只使用使用日期時間的總秒數屬性的對象