Справочный пользовательский элемент управления WPF в коде MainWindowViewModel - PullRequest
0 голосов
/ 25 января 2011

Пользовательский элемент управления находится в Controls \ TabControl.Содержит tabcontrol с 2 tabitems (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 ]

1 голос
/ 25 января 2011

Существуют различные возможности, но если я посмотрю на ваш пример кода, то думаю, что добавлю событие FileSaved в вашу ViewModel и вызову это событие после успешного сохранения.
Из вашего главного окна вы можете зарегистрироваться всобытие и выполнить дальнейшую обработку, такую ​​как фокус нужного элемента управления.
Однако для установки заголовка я бы объявил свойство в вашей ViewModel и связал с ним заголовок RuleTabs.Но очевидно, что вы также можете установить заголовок в событии, но у него есть некоторые ненужные недостатки.

Обновление
При желании приведем краткий пример реализации события и свойства вViewModel.Я предполагаю, что ваша ViewModel реализует INotifyPropertyChanged .Если нет, но он наследуется от DependencyObject, объявите DepencencyProperty только для чтения для FileName вместо свойства clr:

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 голосов
/ 26 января 2011

Вы используете шаблон MVVM, не так ли? Не обращайтесь к свойствам вашего элемента управления, а к свойствам модели представления, к которой привязан элемент управления.

У вас должна быть модель вида для RuleTab; ему необходимо предоставить свойство Filename, к которому привязан Header в RuleTab. Ваш метод просто устанавливает это свойство. (Который, конечно, должен реализовывать уведомление об изменении одним из обычных способов.)

Вообще говоря, каждый раз, когда вы пытаетесь манипулировать элементом управления в представлении кода модели, вы делаете это неправильно. Модели представлений не знают, что существуют элементы управления. Весьма маловероятно, что вы пишете модульные тесты для своих моделей представлений в NUnit (это одна из тех вещей, о которых все говорят, но мало кто делает), но вы по крайней мере должны это делать.

Кроме того, метод, который показывает диалог файла, должен действительно быть методом в представлении, а не моделью представления. Это немного напоминает архитектуру, но общая идея заключается в том, что модель представления вообще не имеет пользовательского интерфейса. Распространенный способ справиться с этим - заставить модель представления реализовать SaveCommand, который вызывает событие при его выполнении, и открытый метод, который фактически сохраняет файл. Представление прослушивает событие, и когда оно возникает, оно отображает диалоговое окно, получает имя файла и вызывает метод в модели представления, если пользователь не отменил. Это, опять же, дает вам то, для чего вы можете написать модульные тесты без использования пользовательского интерфейса.

0 голосов
/ 25 января 2011

WPF объявляет элементы управления в UserControl как private. Чтобы сделать ваш RuleTab public, вы объявляете его FieldModifier как в:

<TextBox x:FieldModifier="Public" />

где x - пространство имен xaml xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml".

...