2014-09-01 3 views
0

У меня довольно сложный вопрос: В моей работе мы используем WPF с стандартами MVVM. В одном из наших UserControls есть дерево, которое загружает все таблицы из базы данных. Для каждой таблицы имя загружается в список по дереву. Когда вы нажимаете на имя таблицы, вы можете добавить данные в эту таблицу с экрана. В основном, он загружает имена столбцов из таблицы сбоку и позволяет вводить данные и сохранять их. Записи затем сохраняются и добавляются как дети в таблицу. Отсюда, выбрав ребенка, вы можете обновить эту информацию.Как сделать datepicker в MVVM treeview WPF

Теперь текущее приложение загружает данные в порядке. Загружаются имена и данные таблицы. Загружаются дочерние данные. Все в порядке, но когда дело доходит до загрузки элементов управления, мы используем только текстовые поля.

На UserControl код:

<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 датаpicker для ONE стол. Так например. В таблице Студенты поля - это имя (varchar), возраст (varchar), DateStarted (дата). Текстовое поле загружается для имени и возраста, но только для DateStarted загружается датапикер.

До сих пор в ресурсах я добавлял <local:DatePicker SelectedDate="{Binding Value}" Visibility="{Binding DateVisible}"/> Так что, когда загружается таблица Student, видимость datepicker изменяется от скрытого до видимого.

Вот образец ViewModel:

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 и выбираю на другой таблице, иногда видна датапикер, хотя для видимости установлено значение Скрытый. И когда выбрана таблица «Студент», в каждом поле есть текстовые поля.

Как мне просто сделать один дампикер для этой таблицы?

Если есть больше информации необходимо, я буду редактировать и обновлять соответственно

EDIT

Скриншоты Вот как в TreeView нагрузки. все таблицы в db перечислены здесь enter image description here Теперь щелчок по таблице, в которой не должно быть datepicker, делает это: enter image description here он добавляет datepicker в этот контейнер дерева. Я хочу устранить это, , и здесь он должен быть enter image description here , но у меня их слишком много, смотрите. здесь должен быть добавлен только один. не весь путь вниз, под каждым текстовым полем.

и видимая настройка - это только временное исправление, пока я не сортирую этот сортировщик даты.видимость может быть решена позже

+0

Можно ли обеспечить скриншот? Я не могу представить, как это работает. Btw. наличие DateVisible в виде строки, а не типа видимости (или преобразования из bool -> Visibility), может быть подвержено ошибкам от орфографических ошибок. – sondergard

ответ

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 объекта типа:

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); 
    } 
} 

Или вы могли бы иметь свойство DataType:

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

пытается реализовать этот DataTemplateSelector. Кстати, что такое отражение? есть ли у меня ссылка для поиска? –

+0

Я обновил ответ, чтобы проиллюстрировать решение отражения – sondergard

+0

спасибо. собираюсь работать над ним и отчитываться через день или два –

Смежные вопросы