2011-04-13 3 views
0

WinForms 앱에 WPF ElementHost이 있습니다. 사용자 정의 컨트롤에는 응용 프로그램에서 제공하는 사용 가능한 명령 트리가 표시되어야하는 텍스트와 TreeView이 있습니다..Net 4 ElementHost (MVVM)의 WPF Cotrol에 바인딩

저는 WPF에 익숙하지 않습니다. (이것은 학습용이므로) 데이터 바인딩에 문제가 있습니다.

CommandTreeViewModel 클래스를 내보기 모델로 사용하도록 만들었습니다. IEnumerable(of CommandViewModel)FirstGeneration 속성이 있습니다. CommandViewModel 클래스는 Children 속성 (다시 IEnumerable(of CommandViewModel))을 포함하여 Command을 설명하는 몇 가지 간단한 속성을 갖습니다.

내 winforms 앱에서 설정 한 WPF User Control에 Public Property ViewModel As CommandTreeViewModel을 추가했습니다.

어떻게 해야할지 모르겠지만 ViewModel 속성에 전달 된 데이터를 가져 와서 TreeView에 바인딩합니다. (그리고 XAML 바인딩의 ViewModel 클래스 a-la MVC를 강력하게 입력 할 수있는 방법이 있습니까?)

필자는 필요한 경우 아래 관련 코드라는 것을 포함 시켰습니다. 당신이 볼 수 있듯이

사용자 컨트롤

Public Class WPFCommandTree 
    Implements INotifyPropertyChanged 

    Public Property ViewModel As CommandTreeViewModel 
     Get 
      Return DirectCast(GetValue(ViewModelProperty), CommandTreeViewModel) 
     End Get 

     Set(ByVal value As CommandTreeViewModel) 
      If Not value.Equals(DirectCast(GetValue(ViewModelProperty), CommandTreeViewModel)) Then 
       SetValue(ViewModelProperty, value) 
       RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("ViewModelProperty")) 
      End If 
     End Set 
    End Property 

    Public Shared ReadOnly ViewModelProperty As DependencyProperty = _ 
     DependencyProperty.Register("ViewModel", 
     GetType(CommandTreeViewModel), GetType(Window), 
     New FrameworkPropertyMetadata(Nothing)) 


    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged 
End Class 

XAML

<UserControl x:Class="WPFCommandTree" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="60" /> 
      <RowDefinition Height="*" /> 
     </Grid.RowDefinitions> 
     <TextBlock FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center">Test</TextBlock> 
     <TreeView ItemsSource="{Binding FirstGeneration}" 
        VerticalAlignment="Stretch" 
        HorizontalAlignment="Stretch" 
        Grid.Row="1" 
        DataContext="{Binding}"> 
      <TreeView.ItemContainerStyle> 
       <Style TargetType="{x:Type TreeViewItem}"> 
        <Setter Property="IsExpanded" 
          Value="{Binding IsExpanded, Mode=TwoWay}" /> 
        <Setter Property="IsSelected" 
          Value="{Binding IsSelected, Mode=TwoWay}" /> 
        <Setter Property="FontWeight" 
          Value="Normal" /> 
        <Style.Triggers> 
         <Trigger Property="IsSelected" Value="True"> 
          <Setter Property="FontWeight" Value="Bold" /> 
         </Trigger> 
        </Style.Triggers> 
       </Style> 
      </TreeView.ItemContainerStyle> 
      <TreeView.ItemTemplate> 
       <HierarchicalDataTemplate ItemsSource="{Binding Children}"> 
        <TextBlock Text="{Binding Name}" /> 
       </HierarchicalDataTemplate> 
      </TreeView.ItemTemplate> 
     </TreeView> 
    </Grid> 
</UserControl> 

보기 모델

Public Class CommandTreeViewModel 
    Public Property RootCommand As CommandViewModel 
    Public Property FirstGeneration As ReadOnlyCollection(Of CommandViewModel) 

    Public Sub New(ByVal RootCommand As Command) 
     _RootCommand = New CommandViewModel(RootCommand) 
     _FirstGeneration = New ReadOnlyCollection(Of CommandViewModel)(New CommandViewModel() {_RootCommand}) 
    End Sub 

    Public Sub New(ByVal RootCommand As CommandViewModel) 
     Me.RootCommand = RootCommand 
     Me.FirstGeneration = New ReadOnlyCollection(Of CommandViewModel)(New CommandViewModel() {_RootCommand}) 
    End Sub 

    Public Sub New(ByVal RootCommands As IEnumerable(Of CommandViewModel)) 
     Me.RootCommand = RootCommands.First 
     Me.FirstGeneration = New ReadOnlyCollection(Of CommandViewModel)(RootCommands.ToList) 
    End Sub 
End Class 


Public Class CommandViewModel 
    Implements INotifyPropertyChanged 

    Public Property Command As Command 
    Public Property Children As ReadOnlyCollection(Of CommandViewModel) 
    Public Property Parent As CommandViewModel 
    Public Property Name As String 

    Private Property _IsSelected As Boolean 
    Public Property IsSelected() As Boolean 
     Get 
      Return _isSelected 
     End Get 
     Set(ByVal value As Boolean) 
      If value <> _isSelected Then 
       _isSelected = value 
       RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("IsSelected")) 
      End If 
     End Set 
    End Property 

    Private Property _IsExpanded As Boolean 
    Public Property IsExpanded() As Boolean 
     Get 
      Return _IsExpanded 
     End Get 
     Set(ByVal value As Boolean) 
      If value <> IsExpanded Then 
       _IsExpanded = value 
       RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("IsExpanded")) 
       If _IsExpanded And _Parent IsNot Nothing Then 
        _Parent.IsExpanded = True 
       End If 
      End If 
     End Set 
    End Property 

    Public Sub New(ByVal Command As Command) 
     Me.New(Command, Nothing) 
    End Sub 


    Private Sub New(ByVal Command As Command, ByVal Parent As CommandViewModel) 
     _Command = Command 
     _Parent = Parent 

     If Command.Children IsNot Nothing AndAlso Command.Children.Count > 0 Then 
      _Children = New ReadOnlyCollection(Of CommandViewModel)(
      Command.Children.Select(Function(x) New CommandViewModel(x, Me) 
      ).ToList) 
     End If 
    End Sub 

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged 
End Class 

, 나는 R 아니에요 내가해야 할 일에 대해 명확하게 설명하고 여러 자습서에서 일부 코드를 함께 해킹하려고 시도했습니다. 대부분은 WPF 만 있습니다.

위를 실행하면 정확하게 양식이로드되지만 양식에 '테스트'텍스트가 표시됩니다. TreeView은 비어 있습니다. 오류가 발생하지 않습니다. 데이터를 올바르게 바인딩하지 않았기 때문에 이것이라고 가정합니다.

마지막으로 DP가되어야 할 부동산 중 어느 것이 불분명합니까? ViewModel, Model Children? 나는 구속력이 어떻게 작용하는지 명확하지 않다.

답변

1

구문 분석 할 코드가 많아 잠시 동안 VB에서 코딩하지 않았지만 적어도 몇 가지 사항을 확인했습니다.

좀 더 간단하게 시작하는 것이 좋습니다. 실제로 시작하기 만하면 여러 단계의 명령이있는 트리 뷰가 아닌 바인딩하기 쉬운 것을 얻으려고 시작하십시오. 계층 적 데이터 템플릿으로 이동하기 전에 플랫 데이터 그리드를 가져 와서 스타일을 추가하십시오 (트리거와 함께!). 한번에 너무 많은 개념을 도입하고 있습니다.

나는 뭔가를 놓치지 않는 한 여기에서 의존성 속성을 사용할 필요가 없다고 생각합니다. 종속성 속성은 주로 사용자 정의 컨트롤을 다른 컨트롤/창에 드롭하고 XAML/Databinding을 통해 속성을 제어 할 수있는 경우에 사용됩니다.

종속성 속성을 통해 viewModel을 설정하려는 것 같습니다. 대신 코드 숨김 - Me.DataContext = New CommandTreeViewModel (내 VB가 녹슬 었음을 기억하십시오 :)처럼)에서 생성자의 DataContext 속성을 설정하십시오.View의 DataContext가 설정되지 않아서 실제로 바인딩이 작동하지 않는 것이 주된 문제입니다.

마지막으로 VS의 디버그 출력 창에 데이터 바인딩 오류가 포함되어야합니다. 이는 바인딩 실패의 원인을 파악하는 데 큰 도움이됩니다.

+0

감사합니다. XAML은 거의 그대로 복사되었으므로 거기에 불필요한 복잡성이 있다는 것을 알고 있습니다. 디버깅하는 동안이를 고려하는 것을 잊었습니다. 'MyBase.DataContext'가 필요한 것 같습니다. 나는 지금 놀거야. 정말 좋은 팁을 가져 주셔서 감사합니다. – Basic

+0

그건 잘못된 바인딩 명령, 특히'DataContext = "{Binding}"대신'DataContext = "{Binding FirstGeneration}"에 비틀 거렸다. 당신의 도움을 주셔서 감사합니다! – Basic

+0

문제 없습니다, 지금 당장 옳은 길을 걷고 있습니다. –

관련 문제