MainWindowViewModel代码中的WPF参考用户控件

时间:2011-01-25 18:58:58

标签: c# wpf user-interface tabcontrol

用户控件位于Controls \ TabControl中。包含带有2个tabitems的tabcontrol(RuleTab和DiagramTab)。

在我的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>

3 个答案:

答案 0 :(得分:1)

有各种可能性,但如果我查看您的代码示例,那么我认为我会向您的ViewModel添加一个事件FileSaved并在成功保存后引发此事件。
在您的MainWindow中,您可以注册此事件并进行进一步处理,例如聚焦所需的控制 但是,为了设置标题,我会在ViewModel中声明一个属性并将RuleTabs标头绑定到它。但显然你也可以在事件中设置标题,但这有一些不必要的缺点。

<强>更新
这里需要一个在ViewModel中实现事件和属性的简短示例。我假设您的ViewModel实现了INotifyPropertyChanged。如果没有,但它派生自DependencyObject,则声明FileName的只读DepencencyProperty而不是clr-property:

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

答案 1 :(得分:0)

WPF将UserControl中的控件声明为private。要使RuleTab publicFieldModifier声明,如下所示:

<TextBox x:FieldModifier="Public" />

其中x是xaml名称空间xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

答案 2 :(得分:0)

你正在使用MVVM模式,不是吗?不访问控件的属性,访问控件绑定的视图模型的属性。

您应该拥有RuleTab的视图模型;它需要公开Filename Header绑定的RuleTab属性。然后您的方法只设置该属性。 (当然,这必须以通常的方式之一实施变更通知。)

一般来说,每当您尝试在视图模型代码中操作控件时,您都在做错了。视图模型不知道控件存在。你不太可能在NUnit中为你的视图模型编写单元测试(这是每个人都谈论但很少有人这样做的事情之一),但你至少应该能够。

此外,显示文件对话框的方法应该是视图中的方法,而不是视图模型。这得到了一点点架构 - astronauty,但一般的想法是视图模型根本没有任何UI。处理此问题的常用方法是让视图模型实现SaveCommand,在执行时引发事件,以及实际保存文件的公共方法。视图侦听事件,当它被引发时,它会显示对话框,获取文件名,如果用户没有取消,则在视图模型上调用该方法。这再次为您提供了一些可以在不涉及UI的情况下编写单元测试的东西。