2014-09-01 45 views
0

我有一個相當複雜的問題: 在我的工作中,我們使用帶有MVVM標準的WPF。 在我們的一個用戶控件上,有一個樹形視圖加載數據庫中的所有表。對於每個表,名稱都由樹視圖加載到列表中。當你點擊表名時,你可以從屏幕上向該表添加數據。 基本上,它從側面的表格加載列名,並讓您輸入數據並保存。記錄然後保存並作爲孩子添加到表格中。從這裏,選擇一個孩子可以讓你更新這些信息。如何在MVVM treeview中製作datepicker WPF

現在,當前的應用程序加載數據的罰款。表格名稱和數據被加載。子數據加載。 一切都很好,但是在加載控件時,我們只使用文本框。

在用戶控件的代碼是:

<UserControl.Resources> 
    <ResourceDictionary> 
     <DataTemplate x:Key="AdditionalItemsTemplate"> 
      <Border> 
       <StackPanel> 
        <Label        
         Content="{Binding Name}" 
         Style="{StaticResource PanelLabelStyle}"/> 
        <TextBox               
         Text="{Binding Value}"        
         Style="{StaticResource TextBoxStyle}"/> 

       </StackPanel> 
      </Border> 
     </DataTemplate> 
    </ResourceDictionary> 
</UserControl.Resources> 
<Border 
    Height="350" 
    Width="{Binding Width}" 
    Style="{StaticResource InnerMenuBorderStyle}"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition/> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto"/> 
      <ColumnDefinition Width="Auto"/> 
      <ColumnDefinition Width="Auto"/> 
     </Grid.ColumnDefinitions> 
     <Border 
      Grid.Row="0" 
      Grid.Column="0" 
      Width="230"     
      IsEnabled="{Binding IsUpdateEnabled}"> 
      <StackPanel> 
       <Border 
        Margin="3,3,3,0" 
        Style="{StaticResource PanelBorderStyle}"> 
        <StackPanel> 
         <Label Style="{StaticResource PanelLabelStyle}"> 
          <TextBlock 
           Text="{Binding TableName}" 
           TextWrapping="WrapWithOverflow"/> 
         </Label> 
         <TextBox 
          Style="{StaticResource TextBoxStyle}" 
          Text="{Binding Value}" 
          TextWrapping="Wrap"/> 
         <ItemsControl 
          Width="222" 
          HorizontalAlignment="Left" 
          ItemsSource="{Binding additionalFields}" Margin="0,0,-226,0" 
          ItemTemplate="{StaticResource AdditionalItemsTemplate}"/> 
        </StackPanel> 
       </Border> 
       <Button  
        Width="70" 
        VerticalAlignment="Top" 
        HorizontalAlignment="Left" 
        Margin="3.5,0,0,0" 
        Template="{StaticResource UpdateButtonTemplate}" 
        Command="{Binding ButtonCommand}" 
        CommandParameter="Update"/> 
      </StackPanel> 
     </Border> 
     <Rectangle 
      Grid.Row="0" 
      Grid.RowSpan="2" 
      Grid.Column="1"    
      HorizontalAlignment="Left" 
      VerticalAlignment="Stretch" 
      Width="2" 
      StrokeDashArray="0.5 1.0 0.3" 
      Stroke="LightGray" 
      Visibility="{Binding IsAddVisible}"/> 
     <Border 
      Grid.Row="0" 
      Grid.Column="2" 
      Width="230"     
      Visibility="{Binding IsAddVisible}"> 
      <StackPanel> 
       <Border 
        Margin="3,3,3,0" 
        Style="{StaticResource PanelBorderStyle}"> 
        <StackPanel> 
         <Label 
          Grid.Row="0" 
          Content="{Binding LabelText}" 
          Style="{StaticResource PanelLabelStyle}"/> 
         <TextBox 
          Grid.Row="1"       
          Text="{Binding NewLookup}"       
          Style="{StaticResource TextBoxStyle}"/> 
         <ItemsControl 
          Width="222" 
          Margin="0,0,-226,0" 
          HorizontalAlignment="Left" 
          ItemsSource="{Binding childAdditionalFields}"         
          ItemTemplate="{StaticResource AdditionalItemsTemplate}"/> 
        </StackPanel> 
       </Border> 
       <Button 
        Grid.Row="2" 
        Width="50" 
        HorizontalAlignment="Left" 
        Margin="3.5,0,0,0" 
        Template="{StaticResource AddButtonTemplate}"     
        Command="{Binding ButtonCommand}" 
        CommandParameter="Add"/> 
      </StackPanel> 
     </Border> 
    </Grid> 
</Border> 

在資源,AdditionalItemsTemplate加載爲每列名稱的標籤,然後將文本框裝有價值,或可用於輸入新值

我想做的只是ONE datepicker ONE表。例如, 。在表Students中,字段是Name(varchar),Age(varchar),DateStarted(date)。一個文本框加載名稱和年齡,但只爲DateStarted日期選擇器應加載。

到目前爲止,在資源中,我添加了<local:DatePicker SelectedDate="{Binding Value}" Visibility="{Binding DateVisible}"/> 因此,當加載表Student時,日期選擇器的可見性從隱藏變爲可見。

這裏是視圖模型的樣本:

public AddUpdateConfigurationViewModel(TreeViewContainer treeViewContainer, List<AddChangeSiteConfigurationViewModel> lookupTypeList, FieldDataResponse fieldDataResponse) 
    { 
     NewLookup = String.Empty; 
     Width = 480; 
     DateVisible = "Hidden"; 
     IsAddVisible = "Hidden"; 
     IsUpdateEnabled = false; 
     if (treeViewContainer.AdditionalFields != null) 
     { 
      if (treeViewContainer.AdditionalFields.Count() > 0) 
      { 
       treeViewContainer.AdditionalFields.RemoveAll(x => x.Name.Contains("ID")); 
       treeViewContainer.AdditionalFields.RemoveAll(x => x.Name.Contains("Guid")); 
      } 
     }  
     if (treeViewContainer.AdditionalFields != null) 
      this.additionalFields = new ObservableCollection<TreeViewContainer>(treeViewContainer.AdditionalFields); 
     if ((treeViewContainer.ParentTable == null) | (treeViewContainer.ParentTable == String.Empty)) 
      IsUpdateEnabled = true; 
     var lookupTypes = lookupTypeList.Where(x => x.Parent_Field == "ID" + treeViewContainer.TableName); 
     if (treeViewContainer.ParentTable == "IsParent") 
     { 
      IsAddVisible = "Visible"; 
      DateVisible = "Hidden"; 
      LabelText = "New " + treeViewContainer.Name; 
      TableName = treeViewContainer.TableName; 
      childAdditionalFields = new ObservableCollection<TreeViewContainer>(); 
      foreach (var additionalField in treeViewContainer.AdditionalFields) 
       childAdditionalFields.Add(new TreeViewContainer(additionalField.Name)); 
      if (treeViewContainer.Name.Equals("Student")) 
      { 

       DateVisible = "Visible"; 

      } 
     } 
     else if (lookupTypes.Count() > 0) 
     { 
      foreach (var lookupType in lookupTypes) 
      { 
       IsAddVisible = "Visible"; 
       LabelText = "New " + lookupType.Name; 
       TableName = lookupType.TableName; 
       childAdditionalFields = new ObservableCollection<TreeViewContainer>(); 
       foreach (var additionalChildField in lookupType.additionalFieldsDictionary) 
        childAdditionalFields.Add(new TreeViewContainer(additionalChildField.Key)); 
      } 
     } 
     else 
      Width = 250;     
     this.Name = treeViewContainer.Name; 
     this.Value = treeViewContainer.Name; 
     this.ID = treeViewContainer.ID; 
     this.treeViewContainer = treeViewContainer; 
     this.lookupTypeList = lookupTypeList; 
     this.fieldDataResponse = fieldDataResponse; 
    } 

我希望這是有道理的。

現在當我加載usercontrol並在另一個表上選擇時,即使將可見性設置爲隱藏,但有時日期選擇器仍可見。 當學生表被選中時,每個字段都有文本框下的日期選擇器。

我該如何着手爲這張桌子做一個日期選擇器?

如果有任何更多的信息需要,我會編輯和更新相應

編輯

截圖 這是怎樣的樹形負荷。 db中的所有表格都在這裏列出 enter image description here 現在點擊一個不應該有日期選擇器的表是這樣做的: enter image description here 它將datepicker添加到這個treeview容器。我想消除這個, ,這是它應該是 enter image description here 但我有太多,請參閱。這裏只能添加一個。並不是每一個文本框下的所有方式。

和可見性設置只是一個臨時修復,直到我得到這個日期選擇器排序。知名度可以稍後解決

+0

是否可以提供屏幕截圖?我無法真正想象它是如何工作的。順便說一句。將DateVisible作爲一個字符串而不是可見性枚舉類型(或從bool - >可見性轉換)可能容易出現拼寫錯誤中的錯誤。試圖實現這個DataTemplateSelector的 – sondergard 2014-09-01 15:09:03

回答

0

我不認爲添加日期選擇器並試圖顯示/隱藏它是最好的方式去。更好的方法是加載與綁定類型相匹配的數據模板。因此,如果該列是日期時間類型,則應加載包含標籤和日期選擇器的數據模板。這是DataTemplateSelector的用途。您創建一個擴展DataTemplateSelector的類,並根據綁定的對象決定返回哪個模板。

<UserControl.Resources> 
    <DataTemplate x:Key="DateTimeFieldTemplate"> 
     <Border> 
      <StackPanel> 
       <Label        
        Content="{Binding Name}" 
        Style="{StaticResource PanelLabelStyle}"/> 
       <local:DatePicker               
        SelectedDate="{Binding Value}"/> 
      </StackPanel> 
     </Border> 
    </DataTemplate> 
    <DataTemplate x:Key="TextFieldTemplate"> 
     <Border> 
      <StackPanel> 
       <Label        
        Content="{Binding Name}" 
        Style="{StaticResource PanelLabelStyle}"/> 
       <TextBox               
        Text="{Binding Value}"        
        Style="{StaticResource TextBoxStyle}"/> 
      </StackPanel> 
     </Border> 
    </DataTemplate> 
    <local:TemplateSelector x:Key="TemplateSelector" DateTimeFieldTemplate="{StaticResource DateTimeFieldTemplate}" TextFieldTemplate="{StaticResource TextFieldTemplate}"/> 
</UserControl.Resources> 
<Grid> 
    <ItemsControl ItemsSource="{Binding Items}" ItemTemplateSelector="{StaticResource TemplateSelector}"/> 
</Grid> 

你說明你有一個名稱和值屬性的原代碼,所以你只需要在如何提供Value屬性是什麼數據類型信息決定。一種方法是將一個接口類型對象的Value屬性:

public interface IBoundDataColumn 
{ 
    public string Name { get; } // Not really necessary for the template selector, but perhaps for completeness 
    public object Value { get; } 
} 

public class DateTimeColumn : IBoundDataColumn 
{ 
    public string Name { get; set; } 
    public object Value { get; set; } 
} 

public class TemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate TextFieldTemplate 
    { 
     get; 
     set; 
    } 

    public DataTemplate DateTimeFieldTemplate 
    { 
     get; 
     set; 
    } 

    public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container) 
    { 
     IBoundDataColumn boundCol = item as IBoundDataColumn; 

     if (boundCol.Value.GetType() == typeof(DateTime)) 
     { 
      return DateTimeFieldTemplate; 
     } 
     else 
     { 
      return TextFieldTemplate; 
     } 

     return base.SelectTemplate(item, container); 
    } 
} 

或者你可以有一個數據類型屬性:

public interface IBoundDataColumn 
{ 
    public Type DataType {get;} 
} 

public class DateTimeColumn : IBoundDataColumn 
{ 
    public string Name {get;set;} 
    public DateTime Value {get;set;} 
    public Type DataType { get { return typeof(DateTime); } } 
} 

或者你可以完全避免的界面和使用反射來獲得動態鍵入:

public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container) 
{ 
    var p = item.GetType().GetProperty("Value"); 

    if (t.PropertyType == typeof(DateTime)) 
    ... 
} 
+0

。順便說一句,反射解決方案是什麼?有沒有鏈接讓我搜索? – 2014-09-03 10:43:17

+0

我已經更新了答案,以說明反思解決方案 – sondergard 2014-09-03 12:34:53

+0

謝謝。會在一兩天內完成並報告 – 2014-09-03 12:46:58