0

Ok, so I've created two things, a MainWindowViewModel and a TabControlViewModel. Within my TabControlViewModel my View is basically a TabControl with 3 tabitems (Welcome/tabItem1/tabItem2).

My goal is when the application starts up I see the welcome tab only and then when I select File -> Open both tabItems become visible and the focus shows my tabItem2 displaying the text file content.

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

I guess my biggest question is, should my Menu commands be in this TabControlViewModel or in my MainWindowViewModel? Many thanks for your patience here folks...:)

mr justinator
  • 73
  • 1
  • 9

3 Answers3

0

You can create ItemsSource property on your custom control using DependencyProperty some tutorial and later bind to it just like you are doing on default controls.

Code for your MyTabControl(I'm assuming all tabs are generated just after InitializeComponent - created in Xaml, so if you are addind any new later you need to update property):

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

This code will be working without any problems but at some point it would be worth for you to invest some time in mvvm as in many cases it's just easier.

bartosz.lipinski
  • 2,627
  • 2
  • 21
  • 34
  • I read about this last week (different link) and spent a long time trying to get it to work. Would be very much appreciative if you could post some code. – mr justinator Jan 24 '11 at 21:00
0

If you use the mvvm-light framework (http://mvvmlight.codeplex.com/) you could have control 1 broadcast a message when an item is double clicked. Then have control 2 subscribed to messages of that type. When it receives the message, it can set the Datacontext to the correct value. This of course assumes you are using mvvm, and each usercontrol has it's own viewmodel.

The broadcast code might look something like this:

public class MainViewModel
{
    public RelayCommand myCommand { get; private set; }
    public MainViewModel()
    {
        myCommand = new RelayCommand( () => SendTheMessage());
    }
    public void SendTheMessage()
    {
        Messenger.Default.Send("I have sent the message");
    }
}

To receiver code looks something like this:

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

        public void DoSomething(string item)
        {
            System.Windows.MessageBox.Show(item);
        }
    }
thorkia
  • 1,972
  • 1
  • 20
  • 26
  • based on things ive read i wasnt sure it was necessary to build this type of application in MVVM model...seems complicated for beginners of my caliber. many thanks – mr justinator Jan 24 '11 at 22:09
0

I've been reading up on view models and don't think it's required for my simple application.

You are almost certainly mistaken here.

In fact, what you're trying to do here is quite simple if you're using a view model: instead of coding up interrelationships between controls, you build a collection of view model objects that's the ItemsSource of both the tab control and the list box.

If you want double-clicking on an item in your list box to do something that affects what's appearing in the tab control, implement a command in the view model and have double-clicking on the item execute the command. The command executes, it makes whatever changes it makes to the view model, the properties that change raise their events, and the display in the tab control changes.

Not only is this something you can write unit tests for (that's another subject), it also decouples the list box and the tab control from each other. You can, for instance, decide to replace the tab control with some other kind of items control (like a Telerik RadPanelBar) and not have to change any code at all. You can do this because the view model is a logical model of the view that's insulated from any of the view's implementation details.

Don't be scared of view models. They're really not complicated. It's a bit annoying to have to implement property-changed notification, but at the end of the day that's a very small price to pay for consistent, simple, flexible software.

Robert Rossney
  • 94,622
  • 24
  • 146
  • 218
  • alright, im convinced :) i ended up starting simple and trying a few things. updated my code at the top so i can get a little clarify! many thanks for your comments and suggestions...i really appreciate it. – mr justinator Jan 27 '11 at 20:42