Пользовательские элементы управления связыванием WPF - PullRequest
0 голосов
/ 24 января 2011

Хорошо, поэтому я создал две вещи, MainWindowViewModel и TabControlViewModel.В моей TabControlViewModel мой View - это, по сути, TabControl с 3 tabitems (Welcome / tabItem1 / tabItem2).

Моя цель - при запуске приложения я вижу только вкладку приветствия, а затем, когда выбираю File -> Open ОбаTabItems становятся видимыми, и фокус показывает, что мой tabItem2 отображает содержимое текстового файла.

MainWindow.Xaml

<Menu DockPanel.Dock="Top" Width="Auto" Height="25" Name="Menu1">
                <MenuItem Header="_File" VerticalContentAlignment="Top" >
                    <MenuItem Header="_New" Command="{Binding NewCommand}" />
                    <MenuItem Header="_Open" Command="{Binding OpenCommand}">

TabControlViewModel.cs

class TabControlViewModel : TabContainer
{

   private DelegateCommand openCommand;
    public ICommand OpenCommand
    {
        get
        {
            if (openCommand == null)
                openCommand = new DelegateCommand(Open);
            return openCommand;
        }
    }

    private void Open(object obj)
    {
        ProcessOpenCommand();
    }

    private void ProcessOpenCommand()
    {
        if (dataChanged)
        {
            SaveFirst();
            ShowOpenDialog();

        }
        else
        {
            ShowOpenDialog();

        }
    }

    private void ShowOpenDialog()
    {
        System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
        ofd.Filter = "Text File (*.txt)|*.txt";

        if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            filePath = ofd.FileName;
            ReadFile(filePath);
            SetTitle(ofd.SafeFileName);
            RuleTab.Focus();
        }
    }

    private string SaveFirst()
    {
        MessageBoxResult mbr = System.Windows.MessageBox.Show("Do you want to save changes?", "Save Changes", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);

        if (mbr == MessageBoxResult.Yes)
        {
            if (filePath != null)
            {
                SaveFile(filePath);
            }
            else
            {
                ProcessSaveCommand();
            }
        }
        else if (mbr == MessageBoxResult.Cancel)
        {
            return "Cancel";
        }
        return "Nothing";
    }

Я думаю, мой самый большой вопросэто, мои команды меню должны быть в этом TabControlViewModel или в моем MainWindowViewModel?Большое спасибо за ваше терпение здесь, ребята ...:)

Ответы [ 3 ]

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

Если вы используете инфраструктуру mvvm-light (http://mvvmlight.codeplex.com/), вы можете иметь элемент управления 1, транслирующий сообщение при двойном щелчке элемента. Затем элемент 2 подписывается на сообщения этого типа.он может установить Datacontext на правильное значение. Это, конечно, предполагает, что вы используете mvvm, и у каждого usercontrol есть своя собственная модель представления.* Для получателя код выглядит примерно так:

    public class myModel
    {
        public myModel()
        {
            Messenger.Default.Register<string>(this, DoSomething);
        }

        public void DoSomething(string item)
        {
            System.Windows.MessageBox.Show(item);
        }
    }
0 голосов
/ 26 января 2011

Я читал о моделях представления и не думаю, что это требуется для моего простого приложения.

Вы почти наверняка ошибаетесь здесь.

На самом деле, то, что вы пытаетесь сделать здесь, довольно просто, если вы используете модель представления: вместо кодирования взаимосвязей между элементами управления вы создаете коллекцию объектов модели представления, которая является ItemsSource обоих элемент управления вкладкой и список.

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

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

Не бойтесь просмотра моделей. Они действительно не сложны. Немного раздражает необходимость реализации уведомлений об изменении свойств, но в конечном итоге это очень небольшая цена за непротиворечивое, простое и гибкое программное обеспечение.

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

Вы можете создать свойство ItemsSource в своем пользовательском элементе управления, используя DependencyProperty некоторый учебник а затем привязать к нему так же, как вы делаете на элементах управления по умолчанию.

Код для вашего MyTabControl (я предполагаю, что все вкладки создаются сразу после InitializeComponent - созданного в Xaml, поэтому, если вы добавляете что-то новое позже, вам нужно обновить свойство):

public partial class MyTabControl
{
    public static readonly DependencyProperty ItemsProperty =
       DependencyProperty.Register(
       "Items",
       typeof(IEnumerable),
       typeof(MyTabControl),
       null);

    public IEnumerable Items
    {
        get { return (IEnumerable)GetValue(ItemsProperty); }
        set { SetValue(ItemsProperty, value); }
    }

    public MyTabControl()
    {
        InitializeComponent();
        Items = tabControl.Items;
    }
}

Этот код будет работать без проблем, но в какой-то момент вам стоит потратить некоторое время на mvvm, поскольку во многих случаях это просто проще.

...