Frage

I googled all I could but could not find exactly what I was looking for. I have few issues...

This is my code structure:

My Command Class:

 public class BrowseCommand : ICommand 
 {
   //Code here
 }

Inside ViewModel:

public class ExampleViewModel
{
    public ExampleViewModel()
    {
        BrowseCommand = new BrowseCommand();
    }

    public ICommand BrowseCommand
    {
        get;
        private set;
    }
  //More Code...
}

MainWindow.xaml.cs:

 public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ExampleViewModel();
    }
}

MainWindow.xaml:

Window x:Class="Ship32RcParser.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" >

   <Grid>
       <Button  Content="Browse" Command="{Binding BrowseCommand}"/>
       <Button  Content="Search" Command="{Binding I_NEED_HELP_HERE}"  />
   </Grid>
</Window>



I understand that my Browse works fine because of MainWindow.xaml.cs has

DataContext = new ExampleViewModel();

However I do not like that

  1. I do not want to have anything in .cs file
  2. How do i have more than one datacontext - meaning if I want to have command from different ViewModel classes... I know its possible but its going to be bit ugly...

When I was searching for solutions I came across dependencies. For example I could do in my xaml file something like this

xmlns:local="clr-namespace:myMvvMwpfProj.ViewModel"

and then use "local". However, when I tried it did not work as I expected it to work... I also saw something like

xmlns:local="using:myMvvMwpfProj.Command"

can someone explain those too please. Does "local" give me an access to classes? If I have CommandA, CommandB, CommandC classes. Should I be able to do local:CommandA.ExecuteFoo ?

I guess the big question is how do I reference/access properties from different objects. in Xaml

thank you all in advance

War es hilfreich?

Lösung 2

You can set up the datacontext in your View with <Grid DataContext = "{Binding}">

You have 1 viewmodel per view but you can have many bound commands! I suggest you look up Josh Smiths RelayCommand as this make this so much easier! A guide is here:

Create a new class

class RelayCommand : ICommand
{
    private Action<object> _action;

    public RelayCommand(Action<object> action)
    {
        _action = action;
    }

    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
            _action(parameter);
    }

    #endregion
}

And in your ViewModel

    public ICommand BrowseCommand {get; set;}
    public ICommand SearchCommand {get; set;}

    public ExampleViewModel()
    {
        this.BrowseCommand = new RelayCommand(new action<object>(MethodNameEnteredHere);
        this.SearchCommand = new RelayCommand(new action<object>(OtherMethodNameEnteredHere);
    }

So, your xaml would be

<Grid DataContext = "{Binding}">
       <Button  Content="Browse" Command="{Binding BrowseCommand}"/>
       <Button  Content="Search" Command="{Binding SearchCommand}"  />
 </Grid>

Andere Tipps

The DataContext in WPF is the data layer that sites behind the UI layer. Bindings are used to query properties from the data layer for use in the UI layer.

If your UI layer is going to have two buttons (Browse and Search), then you typically want your data layer to have two commands: BrowseCommand and SearchCommand

It is possible to write a binding that queries something other than the current DataContext though. I actually wrote another SO answer yesterday about this, which contains some examples.

The most common ways are ElementName or RelativeSource, which will find another UI element in the VisualTree so you can use it as the binding's source, like this:

<Button Command="{Binding ElementName=SomeXAMLObjectName, 
                          Path=DataContext.BrowseCommand}" />

<Button Command="{Binding 
            RelativeSource={RelativeSource AncestorType={x:Type Window}}, 
            Path=DataContext.BrowseCommand}" />

A 3rd option is to create an instance of an object in the <XXXX.Resources> in the XAML, and set the source to that instance using it's x:Key, like this:

<Window.Resources>
    <local:MyViewModel x:Key="MyViewModelInstance" />
</Window.Resources>

...

<Button Command="{Binding Source={StaticResource MyViewModelInstance}, 
                          Path=BrowseCommand}">

You can also set the binding's Source property to a static object so you don't need to create an instance of the object in the .Resources, like this:

<Button Command="{Binding Source={x:Static local:MyStaticClass.BrowseCommand}}">

This only works for static classes though, as it won't actually create a new instance of an object for the binding.

To answer your other question, when you write

xmlns:local="clr-namespace:myMvvMwpfProj.ViewModel"

you are telling the XAML to use "local" as a shortcut to "myMvvMwpfProj.ViewModel" (xmlns stands for XML Namespace), so something like local:MyStaticClass.BrowseCommand means to bind to myMvvMwpfProj.ViewModel.MyStaticClass.BrowseCommand.

If you're new to WPF and MVVM, I'd actually recommend checking out a couple blog articles I wrote specifically for new WPF/MVVM users.

They'll help you get a better understanding of how WPF and the MVVM pattern work.

If you want your view to use objects from various viewmodels you will have to:

  1. Either have some instances in your main ViewModel for the other view models you want to use and thus your binding will be soemthing like {Binding AlternativeViewModelInstance.NewCommand}

  2. Locate the regions in your view that need bindings on a different data context and separate them into different view-viewmodel couples.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top