I want to do the following XAML code in code behind and not sure how to add the GestureService and GestureListner onto the Image.
Xaml code:
<Image Grid.Row="1" x:Name="img" VerticalAlignment="Center" HorizontalAlignment="Center" Width="200">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener/>
</toolkit:GestureService.GestureListener>
</Image>
Code behind equivalent:
Image image = new Image();
//how do I add GestureService and GestureListner?
ContentPanel.Children.Add(image);
Do this:
GestureService.GetGestureListener(image);
Normal approach would be doing it this way:
GestureService.SetGestureListener(image, new GestureListener());
But GetstureService developers have marked SetGestureListener method as obsolete:
"Do not add handlers using this method. Instead, use GetGestureListener, which will create a new instance if one is not already set, to add your handlers to an element."
Related
I'm new in WPF and I start to use the ribbon:RibbonButton as follows:
<ribbon:RibbonButton x:Name="ServerCondition" Label="Server" FontFamily="Palatino Linotype" FontSize="12" BorderThickness="0" Height="50" CornerRadius="10" LargeImageSource="/Economy;component/Images/server_down.ico"/>
Now it comes to change the LargeImageSourse with another one dynamically from code behind.
First of all I don't know if that is posible.
And if it isn't posible... what control I may use to have the ability to change the icon?
If there is someone to assist me, I'll be thankful.
In your code behind, you can change it like so:
ServerCondition.LargeImageSource = new BitmapImage(new Uri("your uri"));
How to load image to WPF in runtime?
Hi I am attempting to attach a function to text box used for entering some input information which is loaded to an interface from resource dictionary. Here is the XML,
<ContentControl>
<Grid>
<Image s:DesignerItem.Code ="1773" IsHitTestVisible="False" Stretch="Fill" Source="../Images/addition.png" ToolTip="Addition" />
<TextBox Height="57" Width="56" Margin="13,13,130,13" BorderThickness="0" FontSize="45" HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" TextChanged="msg_TextChange" KeyUp="msg_MouseDown"/>
<TextBox Height="57" Width="56" Margin="132,13,12,13" BorderThickness="0" FontSize="45" HorizontalAlignment="Center" VerticalAlignment="Center" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" KeyDown="msg_MouseDown"/>
<Button MouseDown="msg" Width="50" Height="20">ck</Button>
</Grid>
</ContentControl>
From the above code, I attempted to use a few different types of control events. I successfully linked the class my functions are going to be placed in using the following lines to link the class to the resource dictionary.
x:Class="DiagramDesigner.CodeBuilding"
x:ClassModifier="public"
Here is the code for the class I am using,
public partial class CodeBuilding : ResourceDictionary
{
public CodeBuilding()
{
InitializeComponent();
}
public void msg_TextChange(object sender,EventArgs e)
{
MessageBox.Show("oh no, you've got me ...");
}
public void msg(object sender, MouseEventArgs e)
{
MessageBox.Show("oh no, you've got me ...");
}
}
As you can see, I am just using a simple message to indicate if the event has been fired, the project successfully builds and runs fine, but when I attempt to trigger any of the
events used in the XML the function tied to the event does not fire at all.
I am not certain if this is the best method of linking a function to an event loaded by a resource dictionary, but can anyone provide some guidance to this problem I am experiencing.
XAML file should be dependent on its partial code behind file for events to work.
Make sure Build Action for code behind file is set as Compile.
Also open your .csproj file in notepad or in any text editor and make sure DepedentUpon attribute is set on XAML file. It will look like this:
<Compile Include="CodeBuilding.xaml.cs">
<DependentUpon>CodeBuilding.xaml</DependentUpon>
</Compile>
On a side note, simple steps to make it work like that are:
Add a blank UserControl in your project. It will automatically do this work for you which I mentioned above.
All you need to do is simply change the XAML file to ResourceDictionary. (Replace UserControl to ResourceDictionary).
And in code behind just change the base class from UserControl to ResourceDictionary.
[Edit #3] - to anyone reading this question: do not under any circumstance use the approach outlined in this question. It is a Coding Horror. I freely admit this, knowing that all programmers have worked themselves into a corner in the past, and (especially when learning a new technology) we all have been led astray by other, well-meaning developers on the interweb. Read the answer by Robert first, then read this question. Please.
[Edit #2b]
I apologize for the length of this question - there is a question in here (at the end!), but I wanted to make sure the source code was explicit. Anyway.
[Edit #2] - question title changed to more accurately reflect the... question.
[Edit] - I've updated some more of the history as to how I ended up at the design / code that I did here: Obligatory Blog Post. If it helps clarify the question below, feel free to read it...
Original question
The application I'm working on uses Prism and WPF, with a number of modules (currently 3), one of which hosts the application menu. Originally, the menu was static with hooks into CompositeCommand / DelegateCommands, which worked great for routing button presses to the appropriate presenter. Each MenuItem used a StackPanel in its header to display the content as a combination of an image and a text label - which was the look I was going for:
<Menu Height="48" Margin="5,0,5,0" Name="MainMenu" VerticalAlignment="Top" Background="Transparent">
<MenuItem Name="MenuFile" AutomationProperties.AutomationId="File">
<MenuItem.Header>
<StackPanel>
<Image Height="24" VerticalAlignment="Center" Source="../Resources/066.png"/>
<ContentPresenter Content="Main"/>
</StackPanel>
</MenuItem.Header>
<MenuItem AutomationProperties.AutomationId="FileExit" Command="{x:Static local:ToolBarCommands.FileExit}">
<MenuItem.Header>
<StackPanel>
<Image Height="24" VerticalAlignment="Center" Source="../Resources/002.png"/>
<ContentPresenter Content="Exit"/>
</StackPanel>
</MenuItem.Header>
</MenuItem>
</MenuItem>
<MenuItem Name="MenuHelp" AutomationProperties.AutomationId="Help" Command="{x:Static local:ToolBarCommands.Help}">
<MenuItem.Header>
<StackPanel>
<Image Height="24" VerticalAlignment="Center" Source="../Resources/152.png"/>
<ContentPresenter Content="Help"/>
</StackPanel>
</MenuItem.Header>
</MenuItem>
</Menu>
Unfortunately, the application has gotten a bit more complex and it is desireable to have other modules register themselves with the menu - hence, I've been looking at making the menu dynamic. The goal is to have other modules (through a service) be able to add commands to the menu at will - for example, Module A will add a menu item in the Toolbar module that calls a handler in Module A. There's a few excellent articles out there on this subject - the two I've looked at are Building a Databound WPF Menu Using a HierarchicalDataTemplate and WPF Sample Series - Databound HierarchicalDataTemplate Menu Sample. Following the advice in the article, I have managed to make a dynamically constructed menu with no obvious data binding problems - it can create a menu with items linked backed to my presentation model, reflecting the structure of an ObservableCollection in the presentation model
Currently, my XAML looks like the following:
<UserControl x:Class="Modules.ToolBar.Views.ToolBarView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:model="clr-namespace:Modules.ToolBar.PresentationModels"
xmlns:local="clr-namespace:Modules.ToolBar">
<UserControl.Resources>
<model:ToolBarPresentationModel x:Key="modelData" />
<HierarchicalDataTemplate DataType="{x:Type model:ToolbarObject}"
ItemsSource="{Binding Path=Children}">
<ContentPresenter Content="{Binding Path=Name}"
Loaded="ContentPresenter_Loaded"
RecognizesAccessKey="True"/>
</HierarchicalDataTemplate>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Source="{StaticResource modelData}"/>
</UserControl.DataContext>
<Menu Height="48" Margin="5,0,5,0" Name="MainMenu" VerticalAlignment="Top" Background="Transparent"
ItemsSource="{Binding}">
</Menu>
</Grid>
</UserControl>
The code behind for the view does the heavy lifting in the ContentPresenter_Loaded method:
private void ContentPresenter_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
ContentPresenter presenter = sender as ContentPresenter;
if (sender != null)
{
DependencyObject parentObject = VisualTreeHelper.GetParent(presenter);
bool bContinue = true;
while (bContinue
|| parentObject == null)
{
if (parentObject is MenuItem)
bContinue = false;
else
parentObject = VisualTreeHelper.GetParent(parentObject);
}
var menuItem = parentObject as MenuItem;
if (menuItem != null)
{
ToolbarObject toolbarObject = menuItem.DataContext as ToolbarObject;
StackPanel panel = new StackPanel();
if (!String.IsNullOrEmpty(toolbarObject.ImageLocation))
{
Image image = new Image();
image.Height = 24;
image.VerticalAlignment = System.Windows.VerticalAlignment.Center;
Binding sourceBinding = new Binding("ImageLocation");
sourceBinding.Mode = BindingMode.TwoWay;
sourceBinding.Source = toolbarObject;
image.SetBinding(Image.SourceProperty, sourceBinding);
panel.Children.Add(image);
}
ContentPresenter contentPresenter = new ContentPresenter();
Binding contentBinding = new Binding("Name");
contentBinding.Mode = BindingMode.TwoWay;
contentBinding.Source = toolbarObject;
contentPresenter.SetBinding(ContentPresenter.ContentProperty, contentBinding);
panel.Children.Add(contentPresenter);
menuItem.Header = panel;
Binding commandBinding = new Binding("Command");
commandBinding.Mode = BindingMode.TwoWay;
commandBinding.Source = toolbarObject;
menuItem.SetBinding(MenuItem.CommandProperty, commandBinding);
}
}
}
As you can see, I'm attempting to recreate the StackPanel / Image / Name combination of the original menu, just doing so in the code behind. Attempting to do this has not worked out so well - while the menu objects are certainly being created, they don't "appear" as anything other than blank, clickable objects - the StackPanel, Image, Name, etc. aren't being rendered. Interestingly enough, it also is causing the original text in the ContentPresent in the HierarchicalDataTemplate to be erased.
The question then, is there a way to set a MenuItem's Header property in the Load event such that it will display on the UserControl properly? Is the fact that the items in the header are not being displayed indicative of a DataBinding problem? If so, what would be the proper way to bind the Header to a transient object (the StackPanel that was created in the load event handler)?
I'm open to changing anything in the code above - this is all sort of prototyping along, trying to figure out the best way to handle dynamic menu creation.
Thanks!
I'll confess that I haven't dug quite as deep into your example as maybe I should, but whenever I see code-behind that's searching the visual tree, I think, could this be handled more explicitly in a view model?
It seems to me in this case that you could come up with a pretty straightforward view model - an object exposing Text, Image, Command, and Children properties, for instance - and then create a simple data template that for presenting it as a MenuItem. Then anything that needs to alter the contents of your menus manipulates this model.
Edit:
Having looked at what you're up to in more detail, and the two examples you've linked to in your blog post, I am banging my head against the desk. Both of those developers appear to be under the misapprehension that the way to set properties on the menu items that are being generated by the template is to search through the visual tree in the ContentPresenter.Load event after they're created. Not so. That's is what the ItemContainerStyle is for.
If you use that, it's quite straightforward to create dynamic menus of the type you're describing. You need a MenuItemViewModel class that has INotifyPropertyChanged implemented and exposes these public properties:
string Text
Uri ImageSource
ICommand Command
ObservableCollection<MenuItemViewModel> Children
Using this:
<Menu DockPanel.Dock="Top" ItemsSource="{DynamicResource Menu}"/>
where the ItemsSource is an ObservableCollection<MenuItemViewModel>, and using this template:
<HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}"
ItemsSource="{Binding Path=Children}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command"
Value="{Binding Command}" />
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ImageSource}" />
<Label Content="{Binding Text}" />
</StackPanel>
</HierarchicalDataTemplate>
the menus in the window exactly represent what's in the collection, and are dynamically updated as items are added and removed, both to the top-level items and to the descendants.
There's no clambering about in the visual tree, no manual creation of objects, no code-behind (other than in the view model, and in whatever populates the collection in the first place).
I've built a pretty thoroughly worked example of this; you can download the project here.
Another possible approach could be having the Menu be a region and agree on a convention so all views added to that region have a ViewModel with a property named MenuHeader. That way, the region adapter can simply get the menu header from the View's Data Context, and set it to the item when adding it.
Something similar is done in Prism with views added to a Tab Region. You can read more here.
I hope this provides some useful guidance.
Thanks,
Damian
I have a visual brush which is a group of shapes, the main colour of which is a dynamic resource itself - so the shape is for example MyShape and the Colour, MyColour which is referenced by the Shape object.
My problem is when I update the colour for this - it only happens the first time the shape is loaded (the colour needs to be set first) however as much as I change the colour it won't update the dynamic resource that uses the colour - how do I make this work?
Just need to make a dynamic resource work within another dynamic resource and have them both update when I change the colour.
I have no idea how to get this to work - I spent time creating a colour-picker for WPF only to find I cannot change the colour of this item - 1-Tier resources work where I set the brush/colour directly but not a colour within another object or 2-Tier Resource.
Edit: My problem seems to be specific to using these in a seperate Resource / Dictionary as my program needs to access this item from a class not the Window, the main example mentioned does not work when the MyColor is in a seperate Resource.
Unless I misunderstand the situation, exactly what you're talking about works pretty well. I just tried it out with this Xaml:
<Window x:Class="ConditionalTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<SolidColorBrush x:Key="MyColor" Color="Aqua" />
<VisualBrush x:Key="MyBrush">
<VisualBrush.Visual>
<Ellipse Height="50" Width="100" Fill="{DynamicResource MyColor}" />
</VisualBrush.Visual>
</VisualBrush>
</Window.Resources>
<Grid Background="{DynamicResource MyBrush}">
<Button Height="30" Width="Auto" VerticalAlignment="Center" HorizontalAlignment="Center" Content="ChangeColor" Click="Button_Click" />
</Grid>
</Window>
And then changed the color in the click handler for that button:
private void Button_Click(object sender, RoutedEventArgs e)
{
((SolidColorBrush)Resources["MyColor"]).Color = Colors.Purple;
}
And it worked like a champ.
Can you post an example of how you are attempting to change the color in the resource dictionary?
When I make a sample app and try to change the resource value it appears that the SolidColorBrush in the resource dictionary has been frozen so it can't be modified. To get around this I just set the new value to a new SolidColorBrush.
I have the following code and basically what i am not able to figure out is how to clone the whole grid and make a blank copy of them side by side.... for a clear understanding this is something to do with hospital application and the grid is related to a pregnancy so when said 'ADD CHILD' button a whole new grid should be created during run time, thanks for the help below is a link that might help people cause i tried it but not sure how to display it
How can you clone a WPF object?
You should put the object you are want to "clone" in a DataTemplate and reference this template from an ItemsControl, then when you need another grid add another item to the items control (or even better to the list the control is bound to) and the ItemsControl will create a new grid and bind it the new object.
For an example take a look at this post on my blog.
Here is an example for this application (I left only the relevant parts and I didn't test it, so there are probably some typos there):
<Window ... >
<Window.Resources>
<DataTemplate x:Key="ChildTemplate">
<Grid>
...
<TextBlock Text="Delivery Date:" Grid.Column="0" Grid.Row="0"/>
<TextBox Text="{Binding DeliveryDate}" Grid.Column="1" Grid.Row="0"/>
<TextBlock Text="Delivery Time:" Grid.Column="0" Grid.Row="1"/>
<TextBox Text="{Binding DeliveryTime}" Grid.Column="1" Grid.Row="1"/>
...
</Grid>
</DataTemplate>
</Window.Resources>
...
<Button Content="AddChild" Click="AddChildClick"/>
...
<ScrollViewer>
<ItemsControl ItemsSource="{Binding AllChildren}" ItemsTemplate="{StaticResource ChildTemplate}">
<ItemsControl.PanelTemplate>
<ItemsPanelTemplate><StackPanel Orientation="Horizontal"/></ItemPanelTemplate>
<ItemsControl.PanelTemplate>
</ScrollViewer>
...
</Window>
And in cs:
Set an object with all the form data as the Window's DataContext. I'll call this class PostDelveryData.
Create another class with the repeating data. I'll call it ChildDeliveryData.
Add a property of type ObservableCollection<ChildDeliveryData> called AllChildren to PostDeliveryData; it's important it'll be ObservableCollection and not any other type of collection.
Now, for the magic:
private void AddChildClick(object sender, RoutedEvetnArgs e)
{
((PostDeliveryData)DataContext).AllChildren.Add(new ChildDeliveryData());
}
And when you add the new item to the list another copy of the entire data template will be added.
I'm not sure that you're using the correct approach here. I would approach the problem by creating a "ChildGridControl" with a Child property, and let the Child property handle the databinding. Adding a new child to the GUI would involve creating a new instance of the ChildGridControl.
If I am understanding correctly, you should create a UserControl, which wraps your Grid and subsequent controls inside. And use this User control anywhere you wanted to replicate that UI.