For localization I have one resx file per XAML file. They lie in the same directory and namespace. The resx name corresponds to the XAML name with the word Resources appended.
I access the resources like this:
<TextBlock Text="{x:Static r:MainWindowResources.SomeText}"/>
Since I find this quite lengthy (and there are even longer class names) I was wondering if there was some way I could define an alias to MainWindowResources. In C# I can do this with a using directive.
It would be a lot easier if the generated resource file wrapper wouldn't be a class with static properties. A possible solution would be to use a wrapper instance which inherits from DynamicObject. You could pass it a type and access the type's static members through it. Then you'd add an instance of this wrapper as a resource in XAML.
But I'd lose IntelliSense support and it probably wouldn't be great performance-wise either.
Another solution would be to use the WPF Localization Extension but I'd also lose IntelliSense support. Plus I'm curios whether there is any other way to create an alias to a static class. :)
No, there is no way to simply alias the class name in Xaml like you would in C# with using.
A custom markup extension with a short name is probably the best you could do, but as you say, you would lose editor completion support. If you're really desperate, you could write a T4 template that would generate an enum with one value for each string in your resource file, and then you could use an enum value as your markup extension parameter with completion support (e.g., {l:MainWindowString SomeText}), but that seems like a lot of work just to shorten some Xaml attributes, and they wouldn't be that much shorter.
I would just stick with what you have.
Related
This is my simple (newbie) understanding:
We have a choice for the Ressource Code Generator: internal or public. The default appears to be internal. I understand the resources are created with an internal or public accessor depending on that choice.
Therefore, if the accessor is public I can use something like:
Text="{x:Static resx:Resources.SomeLabelID}"
... in my XAML.
My question is either/both:
What use is a generated internal accessor when the XAML shown above does not work (more precisely it 'works' in design mode but not at run time thus creating confusion for a newbie)?
Note: There are many answers in SO that simply say to change the accessor to 'public' without explaining why, which I think would by nice to understand, especially since the default appears to be internal.
-OR-
Is there another way to access resource strings (from XAML) when the code is generated with the internal accessor ?
Thank you
Everything defined in XAML is using internal access modifier. That is by design of WPF framework, simply so you will not be able to access locally defined controls in different assembly.
Generally if you are going to use strings for "static" controls (i.e. Label) then you can simply go a head with changing access modifier.
I want to import a new class to an exist assembly. Now my solution is :
Write this class first and build it.
Then check its IL code in ILDASM.
Create new TypeDefinition,Method
Definition and Instruction and then added to the exist assembly.
These would cost me a lot of time as I'm not good at IL and Mono.cecil.
SO I wonder that is there an easy way to import a TypeDefinition to another?like
var type = other_assembly.MainMoudle.Import(CLASS1).Reslove();
other_assembly.MainModule.Types.Add(type)
Unfortunately, the short answer for an easy way is "No". But there is hope.
The problem is that references to the original type are likely scattered throughout the generated IL for that type. An example would be in a property setter that updates the value of a private field. The field that is referenced in that setter is the field that lives in the original property. In fact, even the property setter for the property itself is a reference to a method within the original assembly's type.
To make this work, you need to look at every reference in the generated assembly (structure, variables, instructions, etc), and those that are self-referential must be updated to instead reference the newly created type.
I know that this is a hard problem because I've written code that does part of what you are looking for. My code actually copies the contents of a source type additively to a target type to enable mixins in C#. If you take the time to look over how the code works, then you could modify it. Here are some links to the Bix.Mixers code that you might find useful.
Project: https://github.com/rileywhite/Bix.Mixers.Fody
Structure Wireframe Clone: https://github.com/rileywhite/Bix.Mixers.Fody/blob/master/src/Bix.Mixers/Fody/ILCloning/ClonerGatheringVisitor.cs
Redirecting references from original to created type (see the RootImport methods): https://github.com/rileywhite/Bix.Mixers.Fody/blob/master/src/Bix.Mixers/Fody/ILCloning/ILCloningContext.cs
In Objective-C (probably in C too) I can have a header file which can contain just anything from macros to constants. And any class (actually the file it resides) that imports that header file can see and use whatever there is declared. Isn't there a similar way to do this in C#? I have not found anything helpful so far. What I can do in C# is have a collection of static classes each having constant fields in them. But when I want to access those constants I have no other way but say Classname.ConstantName. That Classname part is really inconvenient.
You can make your life a little easier by specifying an alias for your class name:
using G = MyNamespace.MyClassContainingGlobalConstants;
...
var x = G.MyConstant;
Apart from that, I'm not aware of any C# feature that would allow you to access static class members without some kind of class name. (BTW, VB.NET has Modules for this purpose.)
I'm currently working on DevExpress Report, and I see this kind of syntax everywhere. I wonder what are they? What are they used for? I meant the one within the square bracket []. What do we call it in C#?
[XRDesigner("Rapattoni.ControlLibrary.SFEAmenitiesCtrlTableDesigner," + "Rapattoni.ControlLibrary")] // what is this?
public class SFEAmenitiesCtrl : XRTable
Those are called Attributes.
Attributes can be used to add metadata to your code that can be accessed later via Reflection or, in the case of Aspect Oriented Programming, Attributes can actually modify the execution of code.
The [] syntax above a type or member is called an attribute specification. It allows a developer to apply / associate an attribute with the particular type or member.
It's covered in section 24.2 of the C# language spec
http://www.jaggersoft.com/csharp_standard/24.2.htm
They are called attributes. They are quite useful for providing metadata about the class (data about the data).
They are called Attributes, You can use them to mark classes, methods or properties with some meta-data that you can find by reflection at runtime.
For instance, one common one is Serializable which marks a class as suitable for conversion into an offline form for storage later.
It is called an attribute.
In this case, DevExpress is using custom attributes on their report classes.
If you're interested in why you want to create custom attributes, this article explains it.
Piling on to the previous answers, this is an attribute that takes a string value in its constructor. In this case, the '+' in the middle is a little confusing... it should also work correctly with:
[XRDesigner("Rapattoni.ControlLibrary.SFEAmenitiesCtrlTableDesigner,Rapattoni.ControlLibrary")]
I'm trying to write a strongly typed, localizable DisplayNameAttribute, but I can't get it to even compile. What I'd like to do on my viewmodel properties is something like
[LocalizedDisplayName<HomeResources>(r => r.WelcomeMessage)]
which would basically do the same thing as
[DisplayName("Welcome to my site!")]
except the message is localized. However, I can't get neither the generic constructor working (how do you supply type arguments to a constructor?) nor the choosing of what string to use. The current constructor looks like this
public class LocalizedDisplayNameAttribute<TResource> : DisplayNameAttribute
{
public LocalizedDisplayName(Expression<Func<TResource, string>> resource)
{ // ...
but the compiler complains that the input argument is not a compile time constant, so apparently this way of doing it is not valid.
Is there any way to get a strongly typed, localized attribute for display name? Is there one out there already?
You can't do it via an attribute. Keep in mind that an attribute is purely metadata embedded in an assembly. There's currently no way to embed a code construct such as an expression as metadata.
If you really really wanted to provide a means of specifying this metadata in a strongly typed way, you could write your own ModelMetadataProvider. It's a pretty advanced task, but I'm currently in the middle of a blog post that shows how to write one which I'll post soon hopefully.
Attribute classes cannot be generic.
IMO, the only way you can do that is:
[LocalizedDisplayName("WelcomeMessage")]
In fact framework attributes are not typed (like DefaultPropertyAttribute etc)
Since an attribute can't be generic and its arguments must be constants, you can't do it the way you describe. Anyway, members of the resource classes generated by the designer are static, so you can't access them through a instance.
Another option would be to pass only the name of the resource to the attribute :
[DisplayNameResourceKey("WelcomeMessage")]
When you want to retrieve the actual message, you just call ResourceManager.GetString with the resource key. But of course you lose the strong typing...