If I extend an existing object, like a DataGrid:
public class CustomDataGrid : DataGrid
{
static CustomDataGrid()
{
CommandManager.RegisterClassCommandBinding(
typeof(CustomDataGrid),
new CommandBinding(ApplicationCommands.Paste,
new ExecutedRoutedEventHandler(OnExecutedPaste),
new CanExecuteRoutedEventHandler(OnCanExecutePaste)));
}
...
On the xaml side of things, if I try using a <CustomDataGrid/> I get something like, CustomDataGrid is not supported in a Windows Presentation Foundation (WPF) project. So how do I actually use the extended class on the xaml side?
You need to reference the class by namespace. This involves adding a namespace declaration to the top of your Xaml file, and then using that namespace in your control element.
If we assume that your CustomDataGrid is in a namespace called Rhubarb, in the same assembly as the Xaml you're writing , you'd need to add this attribute to the root tag in your Xaml file (alongside the other xmlns attributes):
xmlns:rhubarb="clr-namespace:Rhubarb"
Then, where you declare your grid, use this element instead:
<rhubarb:CustomDataGrid />
If your cod is in a separate (referenced) assembly, you need to modify the namespace declaration thus:
xmlns:rhubarb="clr-namespace:Rhubarb;assembly=NameOfYourAssembly"
(Note that there's no .dll suffix on the assembly name.)
Related
I have an WPF solution and this solution consist of 3 project:
1-A project that has several WPF user control inside
2-Another project that has several WPF user control inside
3-A project which has Resources for 2 WPF projects above.
As you know, if you have common settings for you views like that
-Using Same FontFamily.
-Using same FontSize
-Using same FontWeight
-Using same BackroundBrush for all your User Controls etc.. You need to declare this setters in you all usercontrol tags like below:
<UserControl ....
FontFamily="{DynamicResource MyFontFamily}"
FontSize="{DynamicResource MyFontSize}"
FontWeight="{DynamicResource MyFontWeight}"
Background="{DynamicResource MyAppBgBrush2}"
Width="250" d:DesignHeight="350">
<Grid/>......
But I dont want to write same setters in all my UserControls. For thi reason, I decided to move this property setting in to a new c# file and locate it in Resource Project.
using System.Windows.Controls;
namespace Resources
{
public class PageBase : UserControl
{
public PageBase()
{
SetResourceReference(FontFamilyProperty, "MyFontFamily");
SetResourceReference(FontSizeProperty, "MyFontSize");
SetResourceReference(FontWeightProperty, "MyFontWeight");
SetResourceReference(BackgroundProperty, "MyAppBgBrush2");
}
}
}
So, In my Resource project, I adited AssemlyInfo.cs file like this:
[assembly: System.Windows.Markup.XmlnsDefinition("http://schemas.sat.com/winfx/2010/xaml/internalresources", "Resources")]
This edit gives me ability to declare/create a user control like below:
<internalresources:PageBase
xmlns:internalresources="http://schemas.sat.com/winfx/2010/xaml/internalresources">
<Grid>DoWhatEver<Grid/>
<internalresources:PageBase/>
From now, I do not have to create a usercontrol view which its tags start with
<UserControl...., I can start with <internalresources:PageBase......
My Question is that, VisualStudio 2010 can show me Design of all my user control bu Expression blend can not. Interesting part is that both in VS and Blend, my project compiling without any error But when I try to open my views in blend it says:
-The namespace 'PageBase' does not exist in namespace "http://schemas.sat.com/winfx/2010/xaml/internalresources"
P.S: References are added properly to my Project and My project was suitable to open with blend.
I am developing a Windows Store project, and I wish to move MainPage.xaml into a folder called Views. After that I want to rename it. I already attempted doing this, but I ended up breaking it (InitializeComponent could not find a definition).
How can I move and rename the page properly?
Actually, it seems that the MainPage type is hard-coded in the auto-generated code.
look at this post to get information on how to change it.
Let's say you renamed it to MyView.xaml, and moved it to Views folder.
You will probably want (not necessary) to also:
1. add ".Views" to the namespace in MyView.xaml.cs
2. add ".Views." to the x:Class tag in MyView.xaml
Now open App.cs, and locate the following line
if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
{
....
}
change MainPage to reference your new page name.
Simply make sure to keep the namespaces between the code behind and the xaml synchronized:
MainPage.xaml.cs:
namespace YourNameSpace.Views
{
public partial class MainPage : UserControl
{
}
}
MainPage.xaml
<UserControl x:Class="YourNameSpace.Views.MainPage"
....>
</UserControl>
Quick note: It's a little different on Windows Phone: the startup page is defined in the DefaultTask section of the WMAppManifest.xml file:
<Tasks>
<DefaultTask Name ="_default" NavigationPage="MainPage.xaml"/>
</Tasks>
This all began as an attempt to have a numeric textbox. That part is irrelevant but it's why I created the following class. (By the way, using VS 2012 Express, WPF, C# code-behind).
using System;
using System.Windows.Controls;
namespace Herculese
{
public class IntBox : TextBox
{
<!-- irrelevant code here-->
}
}
So far, so good. I build and this becomes a control which I proceed to use in the xaml:
<local:IntBox Name="txtBox_heightft" Width="60" TextChanged="txtBox_Numeric_Changed" />
Then in my code behind where I'm trying to refer to the text in the textbox using "txtBox_heightft.Text", I'm informed that "The name 'txtBox_heightft' does not exist in the current context". This confuses me to no end because if I change "local:IntBox" to "TextBox" in the xaml, it works fine but then of course it's a regular textbox and not my modified version. Do I need to add a reference to the class in the codebehind somehow? This is my first attempt at using a class this way, as I've never needed functionality that wasn't provided by default.
The problem is that you are using Name as a dependency property, you need to use x:Name="txtBox_heightft" as an extension property :)
when I extend an asp.net control and place the extended control class in, say, Applicaton_code
(without specifying the namespace) how do i register the control to use it on a webpage?
what assembly name and namespace should be specified?
use :
<%#Register TagPrefix="local" Assembly="App_Code" Namespace="Controls" %>
Also, you HAVE to defines a namespace where to put your controls (from memory, when adding class to App_code, no namespace is generated by default).
namespace Controls {
public class control1 : WebControl {
}
}
and then , in the aspx file
<local:control1 runat="server", id="youreluckyitworks" />
I am currently building an application that consists of several components, each of which is essentially a WPF user control with a little C# code around it for the plugin system to work (using MEF).
The problem I am having is that each component should include an icon and for niceness purposes I defined that as a System.Windows.Media.Brush so I can just use the DrawingBrush exported from Design there. Now I need to access that piece of XAML from non-WPF C# where I currently have the horrible workaround of instantiating the user control and asking it for the resource:
private Brush CachedIcon = null;
public override Brush Icon
{
get
{
if (CachedIcon == null)
{
CachedIcon = (Brush)(new BlahControl().TryFindResource("Icon"));
}
return CachedIcon;
}
}
I couldn't find a way to read that resource (which is a .xaml file, and referenced in a ResourceDictionary in the custom control) from a "normal" C# class. Anything belonging to WPF has that nice TryFindResource method but how to do that otherwise? I don't want to have the XAML file with the icon lying around un-embedded.
In your XAML code make sure the icon resource has the build option set to "Resource", and then reference the resource to make it a xaml static resource
<UserControl.Resources>
<BitmapImage x:Key="icon1" UriSource="Resources/Icon1.ico" />
</UserControl.Resources>
Then in your .Net 2.0 code you will find the resource in the "{xamlName}.g.resource" stream
Example code that loads all icons from a xaml dll into a dictionary:
using System.IO;
using System.Reflection;
using System.Collections;
using System.Resources;
...
var icons = new Dictionary<String, Bitmap>();
var externalBaml = Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "MyXaml.dll"));
Stream resourceStream = externalBaml.GetManifestResourceStream(externalBaml.GetName().Name + ".g.resources");
using (ResourceReader resourceReader = new ResourceReader(resourceStream)) {
foreach (DictionaryEntry resourceEntry in resourceReader) {
if (resourceEntry.Key.ToString().ToUpper().EndsWith(".ICO")) {
icons.Add(resourceEntry.Key.ToString(), Image.FromStream(resourceEntry.Value as Stream) as Bitmap);
}
}
}
My suggestions are:
Provide metadata on your control about where the icon can be found. You can do this with your own custom attribute (see example 1 below). This metadata will allow you to load the icon without creating an instance of the control.
Since you're using MEF, you can use metadata in your export to achieve the same as above. Details here. See example 2 below.
Treat your icon as an ImageSource rather than a Brush. You can use WPF's Image control to show your ImageSource, or you can paint it with an ImageBrush.
Use the technique provided by TFD to read the resource with the name specified in the metadata. Unfortunately, WPF does not appear to provide anything like a BamlReader, which would make it much cleaner to load the WPF resource from a non-WPF context.
Example 1:
[Icon("MyIconResourceName")]
public class BlahControl : Control
{
...
}
Example 2:
[Export(typeof(IApplicationComponent))]
[ExportMetadata("IconResource", "MyIconResourceName")]
public class BlahControl : Control
{
...
}
You can read resources from your assembly as stream.
Example code here:
http://www.wpftutorial.net/ReadWPFResourcesFromWinForms.html
Define the icons at the app level instead of in the control, either in the app.xaml or a master resource dictionary xaml file. Then you can use the same TryFindResource method, but without creating an instance of the control.