Set RowValidationRules Class as a Resource and Reference from Code - wpf

I would like to put my RowValidationRules class as a resource and then reference the Key on the datagrid but I'm not 100% sure on how to get there.
<Window.Resources><helper:AccountRoleValidationRule x:Key="MyAccountRoleValidator" /></Window.Resources>
<DataGrid.RowValidationRules><helper:AccountRoleValidationRule ValidationStep="UpdatedValue" /></DataGrid.RowValidationRules>
I would like to do something like <DataGrid RowValidationRules="{StaticResource MyAccountRoleValidator}" /> but I get 'RowValidationRules' property is read-only and cannot be set from markup.
In the end I'm going to use FindResource("MyAccountRoleValidator") from my .xaml.vb file to check the validation result on my CanSave() ICommand.

Try element syntax:
<DataGrid.RowValidationRules>
<StaticResource ResourceKey="MyAccountRowValidator"/>
</DataGrid.RowValidationRules>
(StaticResource will not show up in the not so intelligent IntelliSense in VS, but when it is written out the property will)

Related

DataBinding to global ObservableCollection

I have a WPF application using MVVM pattern, where I have many ObservableCollections. Instead of putting these ObservableCollections into each ViewModel, I placed them into a static class called Observables, which is a member of static class AppCommon. So I can access all observable collections through AppCommon.Observables.AnyObservableINeed.
Now I need to change bindings of UserControl's so they bind to these global ObservableCollection's but I don't know how to refer to these ObservableCollections without changind the DataContext.
I tried adding namespace like
xmlns:globals="clr-namespace:Demirbaş.Globals"
and then in the ListBox setting the ItemsSource property like
<ListBox ItemsSource="{Binding Source={globals:Observables.TaşınırSınıfları}}"
but that would give me following error:
'{globals:Observables.TaşınırSınıfları}' value is not a valid MarkupExtension expression. Cannot resolve 'Observables.TaşınırSınıfları' in namespace 'clr-namespace:Demirbaş.Globals'. 'Observables.TaşınırSınıfları' must be a subclass of MarkupExtension.
What is the problem here? Am I using the right XAML syntax to bind to these collections?
EDIT
ItemsSource="{Binding Source={x:Static globals:AppCommon.Observables.TaşınırSınıfları}}" gives me error :
Cannot find the type 'AppCommon.Observables'. Note that type names are case sensitive.
I think it cannot refer to nested classes, is it right? What's the solution?
Thanks
I don't know the namespace of your application but try
xmlns:local="clr-namespace:Demirbaş"
<ListBox ItemsSource="{Binding
Source={x:Static local:AppCommon+Observables.TaşınırSınıfları}}" />
You need to use the x:Static markup extension like LPL suggested in a comment to tell WPF it's a static object
<ListBox ItemsSource="{Binding
Source={x:Static globals:Observables.TaşınırSınıfları}}" />
This error can also occur when the namespace reference is not fully qualified and the target binding exists in another assembly.
For example, xmlns:l="clr-namespace:AssemblyA.Namespace;assembly=AssemblyA".
If the specific assembly is not specified, the same error message will be displayed "value is not a valid MarkupExtension expression".

How to specify datacontext in WPF?

I have a class in the ViewModel folder called "MainViewModel", and I want my datacontext to be set to the class. I am doing it the following way, somehow it doesnt seem to work. Does anyone have some ideas? Thanks.
xmlns:ViewModel="clr-namespace:***.***.ViewModel"
<MenuItem Header="always visible" DataContext="{Binding ViewModel:MainViewModel}" IsCheckable="True" IsChecked="{Binding MenuVisible}" />
Many thanks.
As Tim has already noted, you are setting the class definition as your DataContext and not an instance. The example he gave sets the instance in XAML, which is perfectly accurate and gets the job done; however, in my experience you usually have the instance in your code-behind already. To set the DataContext, you would do something along the lines of:
myMenuItem.DataContext = myMainViewModelInstance;
You're setting the class as your datacontext, not an instance of the class. Declare an instance as in the example in this question and bind to it.

loading a silverlight control with a custom constructor

I have a silverlight page in which I am loading a control. This control has its own viewmodel which I pass in to the .xaml.cs file thru its constructor. However I get an error when compiling. This is the error:
{No matching constructor found on type 'MySite.Views.SearchFlyOutWin'}
My main page makes a reference to the 'SearchFlyOutWin' like this
xmlns:part="clr-namespace:MySite.Views;assembly=MySite"
In my mainpage.xaml I have tried to load the control like this
<part:SearchFlyOutWin x:Name="searchFlyOutWin" Visibility="{Binding Converter={StaticResource BooleanToVisibilityConverter}, Path=IsSearchVisible}" />
The constructor in my SearchFlyOutWin.xaml.cs is like this
public SearchFlyOutWin(ISearchFlyoutViewModel viewmodel)
{
InitializeComponent();
DataContext = viewmodel;
}
I get the error described above in my Mainpage.xaml.cs when it calls the InitializeComponent(); method.
I think I probably need to direct the clr to call the correct constructor when loading the searchwin in this line here below
<part:SearchFlyOutWin x:Name="searchFlyOutWin" Visibility="{Binding Converter={StaticResource BooleanToVisibilityConverter}, Path=IsSearchVisible}" />
Any ideas on how to correct this? ...Thanks for your time.
.
I have a silverlight page in which I
am loading a control. This control has
its own viewmodel which I pass in to
the .xaml.cs file thru its
constructor. However I get an error
when compiling. This is the error:
{No matching constructor found on type
'MySite.Views.SearchFlyOutWin'}
If your own control's constructor takes some parameter(s), then you cannot use this control in XAML. In XAML, every control must have a constructor with no parameter. That is why, it shows the error message {No matching constructor found on type 'MySite.Views.SearchFlyOutWin'}, since XAML parser searches a constructor with no parameter in your control called SearchFlyOutWin, and it found none!
One soution is that remove the parameter from constructor, and define your Model in the XAML as resource, then set the DataContext to it. Like this,
<Window.Resources>
<local:SearchFlyoutViewModel x:Key="model"/>
</Window.Resources>
<part:SearchFlyOutWin DataContext="{StaticResource model}"/>
Hope, it solves your problem.
.
If you're committed to passing the viewmodel to the object in the constructor (which I don't think is a bad thing), the only way I've found to do this is to create the object in code and then add it to its parent panel programatically. Setting up bindings in code is also possible, though the syntax is more complex than the XAML syntax. The code might looks something like:
SearchFlyOutWin searchFlyOutWin = new SearchFlyOutWin(viewModel);
Binding b = new Binding("");
b.Source = IsSearchVisible;
b.Converter = new BooleanToVisibilityConverter();
searchFlyOutWin.SetBinding(SearchFlyOutWin.VisibilityProperty, b);
SearchFlyOutWinParentPanel.Children.Add(searchFlyOutWin);
Where SearchFlyOutWinParentPanel is some panel that can accept children. If there's an alternate way to do this in XAML, I'd love to see it, but I haven't found it yet.
You may need to set you viewmodel class to be public.
Because I guess your viewmodel class will be in another namespace other than view.

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>

How to do simple Binding in Silverlight?

I understand that Silverlight 3.0 has binding but just want a simple example on how to use this to read a property from a class.
I have a class called Appointment which as a String property called Location:
Public Property Location() As String
Get
Return _Location
End Get
Set(ByVal Value As String)
_Location = Value
End Set
End Property
With a Private Declaration for the _Location as String of course.
I want a XAML element to bind to this property to display this in a TextElement, but it must be in XAML and not code, for example I want something like this:
<TextBlock Text="{Binding Appointment.Location}"/>
What do I need to do to get this to work?
It has to be a Silverlight 3.0 solution as some WPF features are not present such as DynamicResource which is what I'm used to using.
Just to add that my XAML is being loaded in from a seperate XAML File, this may be a factor in why the binding examples don't seem to work, as there are different XAML files the same Appointment.Location data needs to be applied.
You have two options.
If the "Appointment" class can be used as the DataContext for the control or Window, you can do:
<TextBlock Text="{Binding Location}" />
If, however, "Appointment" is a property of your current DataContext, you need a more complex path for the binding:
<TextBlock Text="{Binding Path=Appointment.Location}" />
Full details are documented in MSDN under the Binding Declarations page. If neither of these are working, make sure you have the DataContext set correctly.
You need something in code, unless you want to declare an instance of Appointment in a resource and bind to that but I doubt thats what you want.
You need to bind the Text property to the Property Path "Location" then assign the DataContext of the containing XAML to an instance of the Appointment:-
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding Location}" />
</Grid>
Then in the control's load event:-
void Page_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = new Appointment() { Location = "SomePlace" };
}
Note in this case I'm using the default Page control.
If I'm reading correctly, you need to create an instance of Appointment, set the DataContext of the control to that instance and modify your binding to just say: Text="{Binding Location}"
Also, consider implementing INotifyPropertyChanged on your Appointment class to allow the data classes to notify the UI of property value changes.

Resources