Get reference to Xaml object in view model - wpf

I have a an object created in Xaml:
<Grid>
<MyObject/>
</Grid>
I need someway to bind the object myObject back to a property in my view model. I dont know whether this is possible, everything ive seen so far binds properties together, but any help would be greatly appreciated.

I am assuming what you want is your ViewModel to hold the actual visual control MyObject in it and your Grid to display it via MVVM.
This is possible through ContentControl in WPF.
Assuming your ViewModel has a property MyObjectView which holds MyObject...
<Grid>
<ContentControl Content="{Binding MyObjectView}" />
</Grid>
Having said that you must take caution that same MyObjectView is not bound to any other content control as that will result in an error
"Specified element is already the logical child of another element.
Disconnect it first"
And if that requirement is possible then you must excercise ContentTemplate option.
Let me know if this helps.

It is possible. It kinda breaks mvvm though.
You can attach an InvokeCommandAction to this object, and bind the CommandParameter to it via ElementBinding. Then in the callback of the command which you defined in the viewmodel, you will have a reference to this object from the CommandParameter.

Related

How can I bind Text property of TextBox (VIEW) to a vaiable (in VIEWMODEL)

I am a newbie in WPF. I was exploring MVVM Pattern for WPF applications. I am having trouble in binding Text property of a TextBox from VIEW to a variable in VIEWMODEL
Here is the TextBox from MainWindow.xaml
<TextBox x:Name="UsernameTxt" Grid.Row="4" materialDesign:HintAssist.Hint="Username"/>
I just need to know how to bind its Text Property to ViewModel Class in Class Library
Thanks
I think it's possible to give a very generic answer to this very generic question.
If the question changes context this answer is very likely to be deleted but here goes anyhow.
You want your viewmodel to be in the datacontext of the textbox. Because datacontext is inherited down the visual tree this usually means you want to set datacontext of your window to an instance of the viewmodel. Or maybe the usercontrol your textbox is in, but we know nothing about your app so let's just cover the simple scenario.
Your options are to instantiate a viewmodel using code or xaml.
If you look at this article:
https://social.technet.microsoft.com/wiki/contents/articles/31915.wpf-mvvm-step-by-step-1.aspx
That instantiates in xaml.
Note the xmlns is
xmlns:local="clr-namespace:wpf_MVVM_Step01"
That's saying where you see some bit of markup which is prefaced "local:" then go get the class out of this namespace.
To point to a different dll ( a class library ) you need to tell it which assembly. You do that by adding ;assembly=Whicheverdll to your equivalent of that xmlns. And of course that won't be local then so give it a different name. You also need a reference to that dll or project added to the entry point exe.
Once you've done all that and your viewmodel is instantiated into memory and in the datacontext of that textbox you need some sort of binding.
Which the article covers but that will be something like:
<TextBox Text="{Binding YourPublicStringProperty}"/>

Call controls inside view(xaml file) in viewmodel

I want to call controls inside view like button and item template inside viewmodel. Please tell how can I do that. My view contains following
<ItemsControl Name="cDetails"
Width="395"
ItemTemplate="{DynamicResource Test}"
ItemsSource="{Binding ViewModels}"
Visibility="{Binding IsLoaded,
Converter={StaticResource visibilityConverter}}">
<Button Name="btnComplete"
Grid.Column="1"
HorizontalAlignment="Center"
Command="{Binding AuditCommand}"
CommandParameter="1">
Complete
</Button>
Please tell how can I call these items in my viewmodel using vb.net.
Thanks
Accessing your view components from inside your viewmodel is not the way to do things in MVVM. Because it is specifically not designed to work this way, you will have to go out of your way to make it work. You should probably investigate how to accomplish your goals using MVVM properly, or forego using MVVM at all and do the work in your code-behind.
Since you have not described what your goal is, it is hard to provide specific recommendations. In general when using MVVM, you manipulate things in your viewmodel and set properties. Your view binds to these properties so that it updates appropriately as they are being set. Your viewmodel does not directly manipulate the views themselves, only the viewmodel properties that they are bound to.
For example, let's say you are updating the text on a TextBlock. You could do something like this in xaml:
<TextBlock Text="{Binding SomeText}" />
Then, your viewmodel (which should implement the INotifyPropertyChanged interface) defines this property and sets it as desired.
public string SomeText
{
get { return _someText; }
set
{
if (_someText != value)
{
_someText = value;
NotifyPropertyChanged("SomeText");
}
}
}
private string _someText;
...
// At any time, you can set the property, and the
// binding will update the text in the control for you.
SomeText = "Some text";
If you absolutely need to manipulate your views from code (or if you are not using MVVM), the appropriate place for that sort of code is the "xaml.cs" file next to your view (the code-behind). You can assign a name to anything in your xaml using syntax like <TextBlock x:Name="SomeTextBlock" /> and then access it from the code-behind as a member variable with the same name. For example, you could do SomeTextBlock.Text = "Some text". However, this is not usually necessary for the vast majority of use cases if you are using MVVM.
You shouldn't try to access controls directly from the ViewModel. The ViewModel must not know about the View implementation.
Instead, in WPF we connect View and ViewModel through Bindings. Bindings connect Properties of controls in the View, with Properties in the ViewModel.
Commands are a special type of Property that can be bound as actions for controls like Button.
In your example, you would need to have these properties in your ViewModel:
A collection named ViewModels
A boolean named IsLoaded
And an ICommand named AuditCommand
By managing those properties, you should be able to control what's shown in your View and its behavior.
If you need more control, create more Bindings to other properties, or create some events in your ViewModel and manage them from your View's code-behind.

XAML DataContext and ViewModel Type

I use MVVM for my application, the DataContext of controls is assigned in my c# code (not in XAML).
Therefore the XAML controls have no idea to which instance type its DataContext is set to. The consequence is that there is no refactoring support and intellisense for the bound properties of my viewmodel in XAML.
Is there a way to tell a control in XAML to which type its DataContext is linked?
So when I modify a property name in my ViewModel or search for all references of that property, I want that this property in XAML bindings gets considered too.
There is no framework support, the best you can do is tell the VS designer the 'shape' of the DataContext so that it will give you hints for the properties. If you want to make your solution more refactor-proof, I would recommend Daniel's T4 metadata solution:
http://www.codeproject.com/KB/codegen/T4Metadata.aspx
This generatesmetadata for your view models which you can reference in the XAML:
<StackPanel DataContext="{Binding Source={StaticResource Person}}">
<TextBlock >Name:</TextBlock>
<TextBox Text="{Binding Path={x:Static Metadata:PersonMetadata.NamePath}}"/>
</StackPanel>
Colin E.
No, as the DataContext can change at runtime, it doesn't make sense to tie this to a particular type.

How to set ItemsSource?

This dialog makes no sense to me
http://img576.imageshack.us/img576/4223/50709706.gif
And I'm having trouble finding good tutorials on it. Most of the examples aren't detailed enough, or do stuff via code, but I'd like to take advantage of the IDE as much as possible.
Whats the difference between ItemsSource and DataContext?
I'd like to bind it to just a List for starters. I don't need SQL or databases or anything fancy. Where would I declare my list? In MainWindow.xaml.cs? How do I get it to appear in that dialog?
Think of "DataContext" as the default value for "Source" in a binding.
When you create a binding, you can specify the path and source, like this (I'll use TextBox as an example):
<TextBox Text="{Binding Path=Foo,Source={StaticResource Bar}}" />
So my TextBox.Text property is bound to a Foo property on an object called Bar (a resource somewhere in the application).
However, if you have a whole bunch of things that you want to bind to properties on Bar, it's easier to set Bar as the DataContext of the parent container. A Binding without a Source will just use the DataContext by default, and DataContext flows through to child controls from the parent. So:
<StackPanel DataContext="{StaticResource Bar}">
<TextBox Text="{Binding Path=Foo}" />
<TextBox Text="{Binding Path=Fizz}" />
<TextBox Text="{Binding Path=Buzz}" />
</StackPanel>
All of the TextBoxes are still binding to properties on Bar, but they're doing it without setting it as a Source explicitly.
So let's have another look at the dialog you posted. It's giving you several options for the "source" of the ItemsSource binding. When you choose "DataContext", you're telling Visual Studio that the ItemsControl doesn't need to know the source - it'll pick it up from the DataContext of the parent container (maybe even the Window itself).
If you chose one of the other options (ElementName, RelativeSource or StaticResource) then you'd be setting the binding's source explicitly for that ItemsControl.
Once you've told it that it's binding to the DataContext, you'll need to drop into the "Path" section of the dialog and tell it which property to bind the items of the control to. In the end, the markup would look something like this (assuming it's a ListBox):
<ListBox ItemsSource="{Binding Path=Foos}" />
So the items in the ListBox are coming from a property called "Foos", and that property is on an object that's set in the DataContext somewhere higher in the logical tree (perhaps on the Window itself).
You rarely need to use the data context of a control outside of the control. The most common use case for setting DataContext(DataContext = this;) is within UserControl's code-behind to make all controls within the UserControl to bind to the control's properties.
When you use a ListBox, setting ItemsSource is sufficient, unless you are doing something funky.
This is a pretty good walkthrough: http://windowsclient.net/learn/video.aspx?v=315275
Specifically, you need to set the DataContext first to tell it where to look for the ItemsSource. The easiest way is to set this on the Window through the XAML:
<Window.DataContext>
<controllers:DownloadManager />
</Window.DataContext>

WPF Update Binding when Bound directly to DataContext w/ Converter

Normally when you want a databound control to 'update,' you use the "PropertyChanged" event to signal to the interface that the data has changed behind the scenes.
For instance, you could have a textblock that is bound to the datacontext with a property "DisplayText"
<TextBlock Text="{Binding Path=DisplayText}"/>
From here, if the DataContext raises the PropertyChanged event with PropertyName "DisplayText," then this textblock's text should update (assuming you didn't change the Mode of the binding).
However, I have a more complicated binding that uses many properties off of the datacontext to determine the final look and feel of the control. To accomplish this, I bind directly to the datacontext and use a converter. In this case I am working with an image source.
<Image Source="{Binding Converter={StaticResource ImageConverter}}"/>
As you can see, I use a {Binding} with no path to bind directly to the datacontext, and I use an ImageConverter to select the image I'm looking for. But now I have no way (that I know of) to tell that binding to update. I tried raising the propertychanged event with "." as the propertyname, which did not work.
Is this possible? Do I have to wrap up the converting logic into a property that the binding can attach to, or is there a way to tell the binding to refresh (without explicitly refreshing the binding)?
Any help would be greatly appreciated.
Thanks!
-Adam
The workaround here was to add a property to my object (to be used as the datacontext) called "Self" , which simply returned
public Object Self { get { return this; }}
Then in the binding I used this property:
<Image Source="{Binding Path=Self, Converter={StaticResource ImageConverter}}"/>
Then when I call
PropertyChanged(this, new PropertyChangedEventArgs("Self"))
it works like a charm.
Thanks all.
I don't believe there is a way of accomplishing exactly what you need with your current converter. As you mentioned, you could do the calculation in your ViewModel, or you could change your converter into an IMulitValueConverter.
From your specific scenario (the converter tied to a ViewModel class, and a few of its properties), I would lean towards implementing the logic in the ViewModel.
Hmm, you don't show the full implementation. But I think it should update, if the value bound to the GUI provides the PropertyChanged-Event.
Regards

Resources