2014-09-01 2 views
0

나는 꽤 복잡한 질문이 있습니다. 제 작품에서는 MVVM 표준과 함께 WPF를 사용합니다. 우리의 UserControl 중 하나에는 데이터베이스에서 모든 테이블을로드하는 트리 뷰가 있습니다. 각 테이블에 대해 이름은 트리 뷰에 의해 목록에로드됩니다. 테이블 이름을 클릭하면 화면에서 해당 테이블에 데이터를 추가 할 수 있습니다. 기본적으로 측면의 테이블에서 열 이름을로드하고 데이터를 입력하고 저장하게합니다. 그런 다음 레코드가 저장되고 테이블에 자식으로 추가됩니다. 여기에서 자녀를 선택하면 해당 정보를 업데이트 할 수 있습니다.MVVM treeview에서 datepicker를 만드는 방법 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 각 열 이름에 대한 레이블을로드하고 텍스트 상자의 값을로드하거나 새 값

를 입력 할 수 있습니다

나는 단지 을 만들고 싶습니다. 에 대한 ONY 날짜표는 ONE입니다. 예를 들면. 표 학생의 필드는 Name (varchar), Age (varchar), DateStarted (date)입니다. Datebox가로드되어야하는 DateStarted에 대해서만 Name 및 Age에 대한 텍스트 상자가로드됩니다.

지금까지는 리소스에 나는 <local:DatePicker SelectedDate="{Binding Value}" Visibility="{Binding DateVisible}"/> 을 추가 했으므로 Student 테이블이로드 될 때 datepicker의 가시성이 숨김에서 표시로 변경되었습니다.

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을로드하고 다른 테이블을 선택하면 가시성이 Hidden으로 설정되어 있더라도 datepicker가 표시되는 경우가 있습니다. 그리고 학생 테이블을 선택하면 모든 필드의 텍스트 상자 아래에 날짜 피커가 있습니다.

이 테이블에 대해 하나의 날짜 피커를 만드는 방법은 무엇입니까? 더 이상의 정보는 필요가있는 경우

, 나는이 방법 트 리뷰로드입니다 따라

편집

스크린 샷 을 편집하고 업데이트합니다. db의 모든 테이블이 여기에 나열됩니다. enter image description here 이제는 datepicker가 없어야하는 테이블을 클릭하십시오. enter image description here 이 트리 뷰 컨테이너에 datepicker가 추가됩니다. 나는 이것을 제거하고 싶습니다. 그리고 이것이 어디에 있어야합니까? enter image description here 하지만 너무 많습니다. 여기에 하나만 추가해야합니다. 모든 텍스트 상자 아래에있는 모든 방법을 사용하십시오.

그리고 Visible 설정은이 datepicker가 정렬 될 때까지 일시적인 수정입니다.시야가 나중에 달라질 수 있습니다

+0

스크린 샷을 제공 할 수 있습니까? 나는 그것이 실제로 어떻게 작동하는지 시각화 할 수 없다. Btw. Visibility enum 유형 (또는 bool -> Visibility에서 변환)이 아닌 문자열로 DateVisible을 사용하면 철자 오류로 인해 오류가 발생할 수 있습니다. – sondergard

답변

0

나는 datepicker를 추가하는 것을 생각하지 않고 표시/숨기기를 시도하는 것이 가장 좋은 방법입니다. 더 좋은 방법은 바인딩 될 타입과 일치하는 데이터 템플릿을로드하는 것입니다. 따라서 열이 datetime 형식 인 경우 레이블과 datepicker가있는 데이터 형식을로드해야합니다. 이것은 DataTemplateSelector을위한 것입니다. DataTemplateSelector를 확장하는 클래스를 만들고 바인딩 할 개체를 기반으로 반환 할 템플릿을 결정합니다. 당신은 당신이 이름 및 값 속성이 원래 코드에서 설명, 그래서 당신은 Value 속성이 무엇인지 데이터 형식에 대한 정보를 제공하는 방법을 결정해야

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

또는 당신은 데이터 형식 속성 수 :

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를 구현하려고합니다. btw, 반사 솔루션은 무엇입니까? 검색 할 수있는 링크가 있습니까? –

+0

반성 솔루션을 설명하기 위해 답변을 업데이트했습니다 – sondergard

+0

감사합니다. 그 일을하고 하루나 이틀 후에 다시보고하자. –

관련 문제