2011-01-25 6 views
0

사용자 정의 컨트롤은 Controls \ TabControl에 있습니다. 2 개의 tabitem (RuleTab 및 DiagramTab)이있는 tabcontrol을 포함합니다. 내 MainWindowViewmodel 클래스에서WPF 참조 MainWindowViewModel의 사용자 정의 컨트롤 코드

나는이 : 그것은 사용자 정의 컨트롤에 있기 때문에

private void ShowSaveDialog() 
    { 
     System.Windows.Forms.SaveFileDialog sfd = new System.Windows.Forms.SaveFileDialog(); 
     sfd.Filter = "Text File (*.txt)|*.txt"; 

     bool? saveResult = sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK; 

     if (saveResult == true) 
     { 
      string s = sfd.FileName; 
      filePath = s; 
      SaveFile(s); 
      SetTitle(sfd.FileName); 
      RuleTab.Header = new System.IO.FileInfo(sfd.FileName).Name; 
      RuleTab.Focus(); 
     } 

RuleTab (TabItem의)이 발견되지 않습니다. 수업 시간에 그것을 어떻게 적절하게 참조합니까?

TabControl.xaml

  x:Name="TabEditor" x:FieldModifier="public" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="423"> 

<TabControl x:Name="tabControl" x:FieldModifier="public" Width="Auto" Padding="0" Margin="3" DataContext="{Binding}"> 
    <local:CloseableTabItem Header="Diagram" x:Name="DiagramTab" x:FieldModifier="public" Height="25"> 
     <Image Height="Auto" x:Name="ResultImage" x:FieldModifier="public" Stretch="Fill" Width="Auto" /> 
    </local:CloseableTabItem> 
    <local:CloseableTabItem Header="Rulebase" x:Name="RuleTab" x:FieldModifier="public" Height="25" > 
     <Grid> 
      <TextBox Height="Auto" x:Name="RuleText" x:FieldModifier="public" Width="Auto" Text="" AcceptsTab="True" AcceptsReturn="True" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Visible" /> 
     </Grid> 
    </local:CloseableTabItem> 
</TabControl> 

답변

1

이 다양한 가능성이 있지만 난 당신의 코드 예를 보면 다음 내가 당신의 ViewModel에 이벤트 FileSaved를 추가하고 sucessfull 후이 이벤트를 발생시킬 것이라고 생각 절약.
MainWindow에서이 이벤트에 등록하고 원하는 컨트롤에 초점을 맞춤으로써 추가 처리를 할 수 있습니다.
그러나 헤더를 설정하려면 ViewModel에 속성을 선언하고 RuleTabs 헤더를 바인딩하십시오. 하지만 분명히 이벤트의 헤더를 설정할 수도 있지만, 여기에는 불필요한 단점이 있습니다.

여기에 이벤트와 당신의 ViewModel의 속성을 구현하는 간단한 예제를 필요에 따라 업데이트
. ViewModel이 INotifyPropertyChanged을 구현한다고 가정합니다. 하지 만이 DependencyObject에서 파생 경우, 대신 CLR-재산의 FileName에 대한 읽기 전용 DepencencyProperty를 선언 :

string m_fileName; 
public event EventHandler FileSaved;  

private void ShowSaveDialog() 
    { 
     System.Windows.Forms.SaveFileDialog sfd = 
      new System.Windows.Forms.SaveFileDialog(); 
     sfd.Filter = "Text File (*.txt)|*.txt"; 

     bool? saveResult = sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK; 

     if (saveResult == true) 
     { 
      string s = sfd.FileName; 
      filePath = s; 
      SaveFile(s); 
      FileName=sfd.FileName; 
      OnFileSaved(EventArgs.Empty); 
     } 
} 

protected virtual void OnFileSaved(EventArgs e){ 
    if(null != FileSaved){ 
     FileSaved(this,e); 
    } 
} 

public string FileName{ 
    get{return m_fileName;} 
    private set{ 
     if(value!=m_fileName){ 
      m_fileName=value; 
      OnPropertyChanged(new PropertyChangedEventArgs("FileName")); 
     } 
    } 
} 
+0

둘 다에 대한 코드 샘플을 제공 할 수 있습니까? 0 –

0

WPF는 UserControlprivate 등의 컨트롤을 선언합니다. 당신의 RuleTabpublic하려면 당신이 같은 FieldModifier로 선언 :

x는 XAML 네임 스페이스 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"입니다
<TextBox x:FieldModifier="Public" /> 

.

+0

ahh 소문자 "public"... thanks :) –

+0

x : FieldModifier를 public으로 설정 한 후에도 여전히 내 MainWindowViewModel 클래스에서 제대로 액세스 할 수 없습니다 (RuleTab.Header = 새 System.IO.FileInfo (ofd.FileName) .Name; .... 제안 사항은 무엇입니까? –

+0

@mr justinator : MainWindow에 대한 참조가 없으면 (올바르게) 가능하지 않습니다. 이 참조를 ViewModel에 직접 제공하지 않는 것이 좋습니다. MVVM 패턴의 많은 유연성을 잃을 것입니다.이 때문에 이벤트 및 FileName 속성을 만드는 것이 좋습니다. 주 창에서 다음을 액세스 할 수 있습니다. 사용자 컨트롤 및 원한다면 텍스트 상자 (예 : TomBot 작성)에 직접 포커스를 지정할 수 있습니다. 그러나 userControl에만 초점을 맞추고 usercontrol이 TextBox로 포커스를 전달하는지 확인합니다. (한 게시물에 대한 많은 질문 :) – HCL

0

MVVM 패턴을 사용하고 있습니까? 컨트롤의 속성에 액세스하지 말고 컨트롤이 바인딩 된 뷰 모델의 속성에 액세스합니다.

RuleTab에 대한보기 모델이 있어야합니다. RuleTab에있는 Header이 바인딩 된 Filename 속성을 노출해야합니다. 그런 다음 메서드는 해당 속성을 설정합니다. (물론, 일반적인 방법 중 하나로 변경 알림을 구현해야합니다.)

일반적으로보기 모델 코드에서 컨트롤을 조작하려고하면 잘못된 것을하는 것입니다. 보기 모델은 컨트롤이 있다는 것을 모릅니다. NUnit에서 여러분의 뷰 모델에 대한 단위 테스트를 작성하는 것은 거의 불가능합니다. 모든 사람들이 이야기하지만 그 중 적은 수는 있지만, 적어도 할 수 있어야합니다.

또한 파일 대화 상자를 표시하는 방법은 실제로보기 모델이 아닌보기의 메소드 여야합니다. 이것은 약간의 아키텍처 - 천문학을 얻지 만, 일반적인 아이디어는 뷰 모델에 UI가 전혀 없다는 것입니다. 이를 처리하는 일반적인 방법은 실행될 때 이벤트를 발생시키는 SaveCommand을 구현하는 뷰 모델과 실제로 파일을 저장하는 public 메서드를 구현하는 것입니다.뷰는 이벤트를 수신하고 이벤트가 발생하면 대화 상자를 표시하고 파일 이름을 가져오고 사용자가 취소하지 않은 경우 뷰 모델의 메서드를 호출합니다. UI를 사용하지 않고 단위 테스트를 작성할 수있는 기능을 제공합니다.

+0

MVVM 모델을 사용하려고합니다. 예 :) 분명히 파악하기가 어렵습니다. 이 응용 프로그램을 작성한 다음이 모델을 사용하여 다시 빌드하려고했지만 훨씬 어려워 보입니다. 더 많은 코드 샘플을 찾으려고 노력할 것입니다. 응답 시간을내어 주셔서 감사합니다. –

+0

MVVM은 생각보다 훨씬 간단합니다. 뷰 모델이'ListBox'에 바인딩 될 때'SelectedItem' 속성을 구현하고 그것에'ListBox.SelectedItem'을 바인딩 할 때처럼 익숙해 져야하는 작은 하위 패턴이 많이 있습니다. 일단 당신이 그들 주위에 당신의 머리를 얻으면 그것은 당신이 당신의 잠에서 할 수있는 것이됩니다. 1 년 전에 작성한 WinForms 앱에서 수정 중이며 매우 단순한 UI에서 코드의 미묘한 복잡성으로 인해 눈물을 흘립니다. 뷰 모델을 구현하고 바인딩 할 수 있다면 훨씬 더 간단해질 것입니다. –

관련 문제