Is it possible to retrieve data inside an XAML file? - c#

In an application I need to use some custom object where each have their own properties and these properties coming from a database so in
<Style x:Key="key1" TargetType="Rectangle">
<Setter Property="Stretch" Value="Fill"/>
<Setter Property="IsHitTestVisible" Value="False"/>
<Setter Property="s:Prop.ID" Value="1234567890-ABC" />
</Style>
I must assign values to the properties. Any help will be appreciated.
Thanks,
Amit

You can use TryFindResource(object key). For example, if your style is under your window's resources and you want to set the second setter to true, you can put this in the code-behind:
((TryFindResource("key1") as Style).Setters[1] as Setter).Value = true;
You could also use binding. Just set the value to Value="{Binding Path=path}" and make your path a dependency property. This also works with multibinding and conversion.

Perhaps MVVM will help you out. Then you have a ViewModel, which exposes your properties to the view. The Model is what the database will deliver. The ViewModel is an adapter between model and view.
Jason Dollinger explains it very good in his video which is available here

Related

Change the control property globally in wpf

I have a back button which is copied almost to all the Controls in my application.
I have set the styles and properties of the button on each individual control (usercontrol)
Now I want to change the text property of the button of all the control (usercontrol).
I don't want to go and change the property of each control.
Please help me setting a global property which sets the property in one place.
Since the style is common to all pages. Create the style without a key/name, just the target type would do.
<Style TargetType="{x:Type Button}">
Then do either of the following -
Add it to the App.XAML for visibility throughout the app
Better approach would be to define a resource dictionary file and import it, wherever you need it.
<Style TargetType="{x:Type Button}">
<Setter Property="Text" Value="{Binding text}" />
<Setter Property="...." Value="{Binding ....}"/>
</Style>
Add this to App.xaml file as you want it to be global style for all your user controls.

usercontrol (?) for WPF reusable menu

I am a beginner at WPF so please excuse me if this question is too simple :)
I have a listbox which I would like to filter by various filter conditions. This listbox I fill with instances of a particular type. Each filter condition is associated with one of the listbox items' properties. (They are like: this or that string property starts with string XXX.)
For this I would need a menu for each property from which users can select the filter conditions they want to filter the items with. Each property of the same type will have the very same set of menu items with the various filter conditions. (For strings: starts with, ends with... for ints: lower than, higher than, etc.)
The menus require some code behind too so I don't want to program these for each property separately.
My problem is that I don't know in what way could I program these. I cannot program them as UserControls because all what I need is MenuItems in a Menu. But I cannot program them as MenuItem derived classes because I would need the XAML for designing them for each type. Could I create a MenuItem derived class with a XAML somehow? Or do you have any other suggestions?
In WPF, we work with data elements whose public properties are data bound to the properties of various UI controls via DataTemplates. Please see the Data Templating Overview page on MSDN for the full story.
In order to do this, we develop custom classes that contain all of the necessary properties that we need to display and then we declare one or more DataTemplates that define the binding connections between the classes and the UI controls, or MenuItems in your case.
The benefit of this is that in order to display a Menu in the UI, you just need to data bind one of your custom menu class objects to a control in the UI and let the DataTemplate do the rest. So if you want to change the menu contents, you just need to change the data item that is data bound to the Menu.
So to answer your question directly, a Menu control would be most suitable for you to use, but you don't store the Menu properties in your code behind... you store the property values in your custom classes that will be data bound to the Menu control properties:
<Menu ItemsSource="{Binding CollectionOfYourCustomClassItems}" ... />
It is worth pointing out that you may need to set the child MenuItem properties in a Style and not a DataTemplate as usual (taken from the accepted answer to the WPF MenuItem : Mix databound items and static content question (which I recommend that you read) here on Stack Overflow):
<MenuItem Header="_Recent Files" ItemsSource="{Binding Commands,Mode=OneWay}">
<MenuItem.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Path=ShortName}" />
<Setter Property="ToolTip" Value="{Binding Path=FileName}" />
<Setter Property="Command" Value="{Binding Path=OpenCommand}" />
<Setter Property="CommandParameter" Value="{Binding Path=OpenParameter}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSeparator}" Value="true">
<Setter Property="MenuItem.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Separator Style="{DynamicResource {x:Static MenuItem.SeparatorStyleKey}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
You will find many more tutorials and related questions regarding data binding to MenuItems online, so I won't go over everything again here. Please see the following article to start with:
Binding menus using HeirarchicalDataTemplates

Simple Search DataGrid

Firstly let me clarify (if the title wasn't clear enough): I'm discussing System.Windows.Controls.DataGrid from the .NET 4.0 Framework, not the toolkit edition.
I have a data grid which i read in from a csv which can change with every load.
I am trying to create a simple search, I have been trying to use;
http://www.codeproject.com/KB/WPF/FirefoxLikeSearchWithMVVM.aspx
http://manfred-ramoser.blogspot.com/2009/11/search-highlighting-in-wpf-datagrid.html
and others, but there all seem very complicated for a simple task, can anyone help, just to be clear a filtering system is not want i am after, thank you.
For my project i did a search function this way :
i added a 'FilterResult' Boolean property to the ViewModel of my data. It is implementing NotifyPropertyChanged.
So i perform the filter on my list of object with simple foreach loop and i set/unset FilterResult
And in the 'Style' of the DataGridRow i put a Setter on Visibility depending upon this FilterResult
<Style TargetType="{x:Type DataGridRow}" x:Key="EventColorRowStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding FilterResult}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
This simpler and much faster than using the Filter of a CollectionView, but still i can point you on what msdn says about it : http://msdn.microsoft.com/en-us/library/ff407126.aspx

Add items at runtime to a databound context menu

I have a requirement to show a list of items in a context menu. In addition to this, I need to show the frequently used items (configurable by user) on the top, followed by a separator, and then the standard list of all the items. I know, I can add all the items to context menu at runtime but I want to explore different options too. The question is - is it possible to:
Bind the standard list in xaml and then add the frequently used items at runtime.
OR
Bind the context menu to two separate list
OR
Any other better option
Please note that I need to maintain two separate lists due to some technical reasons.
I am not showing any existing code because this question may be considered as a generic question and may apply to any control.
The second option is doable using a CompositeCollection, however the binding capabilities are a bit dimished (cannot use DataContext, ElementName or RelativeSource) in the CollectionContainer.Collection-Binding.
This answer of mine on another question shows two ways in which you can bind. If you cannot make do with those restrictions you will have to create the composite collection in code-behind.
I would manage my menus in the ViewModels, not in the XAML. My ViewModel would be responsible for returning a collection that combines both the standard Menu collection, and the custom UserCollection.
Usually I separate the items with a null value, and use a DataTrigger to draw the template as a Separator if the item is null.
Something like this:
myMenu.AddRange(UserMenu);
myMenu.Add(null);
myMenu.AddRange(StandardMenu);
and the XAML...
<ContextMenu ItemsSource="{Binding MyMenu}">
<ContextMenu.Resources>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Template"
Value="{StaticResource MyMenuItemTemplate}" />
<Style.Triggers>
<DataTrigger Binding="{Binding }" Value="{x:Null}">
<Setter Property="Template"
Value="{StaticResource MySeparatorTemplate}" />
</DataTrigger>
</Style.Resources>
</Style>
</ContextMenu.Resources>
</ContextMenu>

WPF: How do I handle an event from a Model to dynamically update xaml in MVVM

I've hit a bit of a dead end in trying to figure this one out... Using the MVVM pattern in WPF, our C# Model fires an event to say something has happened. I want to be able handle that event in my ViewModel and then either kick of a storyboard or change the visibility of a hidden panel on the current Xaml Page. This has to be handled with no Code Behind.
I can sync for the event in my ViewModel, update a property to say what the name of that event is and fire a NotifyPropertyChanged even but how do I get that to either kick off a storyboard or map to a boolean true/false on the Visibility property of my Grid? The property I bind to hs to be the event name as different grids may be shown based on different events so I need a way of mapping this to a boolean. However the ideal solution would be to kick off a storyboard. I've looked at DataTriggers but they all seem to be linked to styles and not to actual pages.
Any ideas of how I can achieve this?
Thanks!
I've used this in the past to kick off a storyboard in code-behind
Storyboard animation = (Storyboard)this.FindResource("ShowPanelStoryboard");
animation.Begin();
This code goes behind the View, not in the ViewModel. Personally, I don't mind some code behind my View providing it is only related the View. In the project I used this in, I added a listener to the VisibilityChanged event and when it got changed to Visible, I ran the storyboard.
As for showing your popup, there's a few ways. One of my favorites was just adding an IsPopupShown property to the ViewModel, binding my panel's visibility to it, and setting it to true anytime the popup should be shown. The ViewModel then handles the events that trigger the popup being shown or not.
An alternative as suggested by Dave White is to use a converter. If your value is not always true/false then you could create a converter that checks if a bound value is equal to the ConverterParameter, and return a Visibility value.
From your comment, it seems to me like what you may want to do is expose an Event property of type object in your view model. When the view model receives an event, it sets Event to an object of a type appropriate for that event. In your XAML, you have this:
<ContentControl Content="{Binding Event}"/>
and in the resource dictionary define a DataTemplate for each specific type of event you want to display. If Event is null, nothing gets displayed. If Event contains an object that you've defined a DataTemplate for, it gets displayed using that template.
Yes, you'll need to create a class for each type of event (if you don't already have one).
Another way is to implement the poor man's template selector:
<TextBlock Text="This is displayed if Foo contains 'BAR'">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Property="Foo" Value="BAR">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text="This is displayed if Foo contains 'BAZ'">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Property="Foo" Value="BAZ">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
It's kind of stupidly verbose, but it's an easy way to handling a lot of mutually-exclusive display options.
Bind the Visibility property on your grid, in Xaml, to the boolean property on your ViewModel.
<Grid Visibility="{Binding Path=VisiblePropertyOnViewModel}">
Now do whatever you need in your ViewModel and set the property. As long as it does INotifyPropertyChanged or is a DependencyProperty, it will work.
I'd have to do more digging to figure out how to kick off a Storyboard, but I have no doubt it would be almost as easy. Storyboards can be kicked off by PropertyTriggers as well I believe. I'll leave this to get you started.

Categories