用户控件位于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>
答案 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
public
用FieldModifier
声明,如下所示:
<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的情况下编写单元测试的东西。