2014-01-06 3 views
2

MainWindow.xaml, MainwindowViewModel.cs, HaemogramReport.xaml 및 HaemogramReport.xaml.cs가 있습니다. 내 프로젝트에도 다른 파일이 있지만 위의 네 가지 파일에 문제가 있습니다. 다른 사람들이 문제를 파악할 수 있도록 여기에 최소 코드를 게시하고 있습니다. 나는 어떤을 클릭하면WPF에서 바인딩이 예상대로 작동하지 않습니다.

<Page.DataContext> 
    <vm:MainWindowViewModel /> 
</Page.DataContext> 

<Grid DataContext="{Binding Source={StaticResource Settings}}" PreviewMouseDown="Object_Selection" x:Name="Root"> 

    <Border Style="{StaticResource BorderStyle}" x:Name="HaemogramTestBorder" 
      Grid.Row="{Binding Default.HaemogramTestGridRow}" Grid.Column="{Binding Default.HaemogramTestGridColumn}" 
      Grid.RowSpan="{Binding Default.HaemogramTestGridRowSpan}" Grid.ColumnSpan="{Binding Default.HaemogramTestGridColumnSpan}"> 
     <Grid> 
      <Rectangle Fill="Transparent" x:Name="HaemogramTestRectangle"/> 
      <TextBlock x:Name="HaemogramTestTextBlock" 
         Text="{Binding Default.HaemogramTestText}" Visibility="{Binding Default.HaemogramTestVisibility}" 
         Background="{Binding Default.HaemogramTestBackground, Converter={StaticResource colorToSolidColorBrushConverter}}" 
         Foreground="{Binding Default.HaemogramTestForeground, Converter={StaticResource colorToSolidColorBrushConverter}}" 
         FontFamily="{Binding Default.HaemogramTestFontFamily, Converter={StaticResource stringToFontFamilyConverter}}" 
         FontSize="{Binding Default.HaemogramTestFontSize}" 
         FontWeight="{Binding Default.HaemogramTestFontWeight}" FontStyle="{Binding Default.HaemogramTestFontStyle}" 
         HorizontalAlignment="{Binding Default.HaemogramTestHorizontalAlignment}" 
         VerticalAlignment="{Binding Default.HaemogramTestVerticalAlignment}" 
         Margin="{Binding Default.HaemogramTestMargin}" /> 
     </Grid> 
    </Border> 

</Grid> 

:

지금 HaemogramReport.xaml에서 내가 좋아하는 ContentControl 등 예를 HaemogramReport.xaml를 들어

보인다, Grid, TextBox, TextBlock, Rectangle, Border 같은 일부 컨트롤을 선언 위의 선언 된 요소의 요소 인 Root이라는 표의 mousedown 이벤트가 발생합니다.

해당 이벤트 처리기는 HaemogramReport.xmal.cs입니다. 여기입니다 :

private FrameworkElement selectedObj; 
public FrameworkElement SelectedObj 
{ 
    get 
    { 
     return selectedObj; 
    } 
    set 
    { 
     selectedObj = value; 
     OnPropertyChanged("SelectedObj"); 
    } 
} 

하세요 : 그리드의

private void Object_Selection(object sender, MouseButtonEventArgs e) 
{ 
    var mouseWasDownOn = e.Source as FrameworkElement; 

    if (mouseWasDownOn != null) 
    { 

     foreach (Border border in FindVisualChildren<Border>(Root)) 
     { 
      border.BorderBrush = Brushes.Transparent; 
     } 

     if (!(mouseWasDownOn is Border)) 
     { 
      FindParent<Border>(mouseWasDownOn).BorderBrush = Brushes.Orange; 
     } 

     MainWindowViewModel mwvm = new MainWindowViewModel(); 
     mwvm.SelectedObj = mouseWasDownOn; 

    } 
} 

public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject 
{ 
    if (depObj != null) 
    { 
     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(depObj, i); 
      if (child != null && child is T) 
      { 
       yield return (T)child; 
      } 

      foreach (T childOfChild in FindVisualChildren<T>(child)) 
      { 
       yield return childOfChild; 
      } 
     } 
    } 
} 

public static T FindParent<T>(DependencyObject child) where T : DependencyObject 
{ 
    //get parent item 
    DependencyObject parentObject = VisualTreeHelper.GetParent(child); 

    //we've reached the end of the tree 
    if (parentObject == null) return null; 

    //check if the parent matches the type we're looking for 
    T parent = parentObject as T; 
    if (parent != null) 
     return parent; 
    else 
     return FindParent<T>(parentObject); 
} 

mouseDown에서 핸들러가 Root 이름, 나는 다음과 같이 mwvm.SelectedObj = mouseWasDownOn;

SelectedObj이 MainwindowViewModel.cs에 선언 형 FrameworkElement의 속성이라고 내 MainWindow 예를 들어 그 안에 그리드 및 textBox 있습니다. 문제가있는 바인딩은 여기에 선언되어 있습니다. 위의 코드를 사용하여

<Window.DataContext> 
    <vm:MainWindowViewModel /> 
</Window.DataContext> 

<Grid DataContext="{Binding SelectedObj, UpdateSourceTrigger=PropertyChanged}"> 
    <TextBox Text="{Binding Text, UpdateSourceTrigger=PropertyChanged, TargetNullValue='null', FallbackValue='Error'}"/> 
</Grid> 

, 나는 항상 위의 텍스트 상자에 텍스트 Error를 얻을 : XAML는 것 같습니다. 다음과 같이 나는이 바인딩 오류가있을 수 있다는 생각 첫 번째 기회에서

, 그래서 내 MainWindowViewModel.cs을 변경 :

public class MainWindowViewModel : INotifyPropertyChanged 
{ 
    public MainWindowViewModel() 
    { 
     SelectedObj = txt; 
    } 

    TextBlock txt = new TextBlock() 
    { 
     Text = "123" 
    }; 

    private FrameworkElement selectedObj; 
    public FrameworkElement SelectedObj 
    { 
     get 
     { 
      return selectedObj; 
     } 
     set 
     { 
      selectedObj = value; 
      OnPropertyChanged("SelectedObj"); 
     } 
    } 
} 

을 위와 같이 변경 한 후 나는 텍스트 상자에 123을 볼 수 있습니다 내 프로젝트를 실행할 때 아무 요소 나 클릭하면 텍스트 상자의 텍스트가 변경되지 않습니다.

이제는 바인딩 오류 인 경우 두 번째 예에서는 텍스트 상자에 123이 표시되는 반면 첫 번째 예에서는 대체 값인 Error - 대체 값이 표시됩니다.

그리고 바인딩 오류가 아니라면 위의 코드에서 어떤 문제가 있습니까?

내가 디버깅 업데이트, 나는 SelectedObjget 부분이 호출되지 않습니다 것을 발견했다. 하지만 왜 그런지 몰라?

업데이트 - 리드 Copsey 여기

나의 새로운 클래스입니다 :

public class DesignMethods 
{ 

    public static void FindCurrentlyClickedElement(DependencyObject Root, MouseButtonEventArgs e, MainWindowViewModel vm) 
    { 
     var mouseWasDownOn = e.OriginalSource as FrameworkElement; 

     if (mouseWasDownOn != null) 
     { 

      foreach (Border border in FindVisualChildren<Border>(Root)) 
      { 
       border.BorderBrush = Brushes.Transparent; 
      } 

      if (!(mouseWasDownOn is Border)) 
      { 
       FindParent<Border>(mouseWasDownOn).BorderBrush = Brushes.Orange; 
      } 

      vm.SelectedObj = mouseWasDownOn; 

     } 
    } 

    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject 
    { 
     if (depObj != null) 
     { 
      for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) 
      { 
       DependencyObject child = VisualTreeHelper.GetChild(depObj, i); 
       if (child != null && child is T) 
       { 
        yield return (T)child; 
       } 

       foreach (T childOfChild in FindVisualChildren<T>(child)) 
       { 
        yield return childOfChild; 
       } 
      } 
     } 
    } 

    public static T FindParent<T>(DependencyObject child) where T : DependencyObject 
    { 
     //get parent item 
     DependencyObject parentObject = VisualTreeHelper.GetParent(child); 

     //we've reached the end of the tree 
     if (parentObject == null) return null; 

     //check if the parent matches the type we're looking for 
     T parent = parentObject as T; 
     if (parent != null) 
      return parent; 
     else 
      return FindParent<T>(parentObject); 
    } 

} 

내가 그것을 사용 좋아 :

private void Object_Selection(object sender, MouseButtonEventArgs e) 
{ 
    DesignMethods.FindCurrentlyClickedElement(Root, e, this.DataContext as MainWindowViewModel); 
} 

답변

2

입니다 수있는 텍스트에 바인딩 업데이트 시도 기존 모델을 사용하지 않고 ViewModel의 새 인스턴스를 만드는 중입니다.

// This is not the same instance you're binding to! 
// MainWindowViewModel mwvm = new MainWindowViewModel(); 

// Get the existing one instead 
var mwvm = this.DataContext as MainWindowViewModel; 
mwvm.SelectedObj = mouseWasDownOn; 

여기서 "ViewModel"이라는 용어는 사용하지 않을 것입니다. 당신이하고있는 일은 MVVM의 정상적인 목표와 거의 반대 방향 인 양방향에서 일어나는 커플 링을 통해 DataContext 인스턴스를 뷰에 단단히 연결하는 전형적인 MVVM 시나리오가 아닙니다.


편집 :

또한 SelectedObj 대한 바인딩을 업데이트해야 할 수도 있습니다. 나는 당신의 실수가 대신 DependencyProperties의 "일반"속성을 사용하고 있는지 것 같아요

<Grid> 
    <TextBox Text="{Binding SelectedObj.Text, UpdateSourceTrigger=PropertyChanged, TargetNullValue='null', FallbackValue='Error'}"/> 
</Grid> 
+0

2 일 전이 질문에 답했습니다. 이제 새로운 클래스에서'Object_Selection'을 옮겨서 여러 곳에서 사용할 수있게되었습니다. 또한 나는이 방법을'정적'으로 표시했다. 그리고 저는'이'를 사용할 수 없습니다. 그래서'MainWindowViewModel'의 Current Instance를 전달해야한다고 생각합니다. 하지만 여전히 출력에 변화가 없습니다. – Khushi

+0

자세한 내용은 업데이트 된 질문을 참조하십시오. 또한 xaml에 내 datacontext를 선언합니다. 언급 한 코드에 영향을 미칩니 까? – Khushi

+0

@Khushi VM의 적절한 인스턴스를 변경 하시겠습니까? setter에 중단 점을 넣으면 변경 내용이 표시됩니까? –

0

시도는 소스 대신 OriginalSource을 사용 :

var mouseWasDownOn = e.OriginalSource as FrameworkElement; 

복합 컨트롤을 처리 할 때 Source 속성이 있기 때문에 OriginalSource 개체 (사용자의 경우 그리드)가 포함 된 부모가 될 수 있습니다.

+0

아니요, 디버깅 할 때 중단 점을 유지했으며 mouseWasDownOn의 값은 항상 클릭하는 요소라고 생각합니다. 내가 말한 코드가 문제의 원인이라고 생각하지 않습니다. – Khushi

0

나는 당신의 오류가 FrameworkElement가 Text 속성 http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement(v=vs.110).aspx

을하지 않는 것 같아요

enter image description here

편집 : 당신의 문제는 당신이

{Binding SelectedObj.Text} 
+0

네, 당신은 어느 정도까지 수정되었습니다. 그래서 FrameworkElement를 Object로 대체했습니다. Object에는 Text 속성이 있습니다. – Khushi

+0

{Binding SelectedObj.Text} – DLeh

+0

에 텍스트 바인딩을 업데이트하면 어떻게됩니까? 잠깐 확인하고 있습니다. – Khushi

0

: 나는에 XAML 세트 시도 추천 할 것입니다.

당신은 당신이 당신의 자신의 속성을 정의하고 싶을 때

는 "그들이 스타일, 데이터 바인딩, 상속을 포함한 윈도우 프리젠 테이션 파운데이션 (WPF) 기능, 의 많은 측면을 지원하기 위해 마이크로 소프트의 설명에서 볼 수 있듯이, 애니메이션 및 기본값 인 값이 있으면 종속성 속성으로 구현해야합니다. "

완전히 이러한 링크

http://msdn.microsoft.com/en-us/library/system.windows.dependencyproperty(v=vs.110).aspx

http://msdn.microsoft.com/en-us/library/ms750428(v=vs.110).aspx

또는 단순히 종속성을 찾습니다에서 봐 WPF

에서 제공하는 모든 자원을 사용하는 속성의 정확한 종류 google에서 속성 WCF.

또 다른 유용한 링크

이러한 속성의 차이가 나는 비슷한 문제가 있었을 때 내가 사용

https://stackoverflow.com/a/3674727

이해합니다.

희망이 있습니다.

관련 문제