I was trying a piece of code and I was amazed to see that Math.Round(4.5) results to 4! 1.5 leads to 2, 2.5 leads also to 2, 3.5 leads to 4, as does 4.5. According to the MSDN documentation on Math.Round, The behavior of this method follows IEEE Standard 754, section 4. This kind of rounding is sometimes called rounding to nearest, or banker's rounding. It minimizes rounding errors that result from consistently rounding a midpoint value in a single direction. To control the type of rounding used by the Round method, call the Math.Round(Double, MidpointRounding) overload. That's nice and everything, but it contradicts the description of the method on the same page: Rounds a double-precision floating-point value to the nearest integral value. It also contradicts the behaviour of Javascript's Math.round in Microsoft's browser Internet Explorer.
The solution for this is to use the overload Math.Round(value,MidpointRounding.AwayFromZero). Math.Round(4.5,MidpointRounding.AwayFromZero) equals 5. If you don't know that, like I did after 5 years of .Net, you are pretty much screwed. So be wary of helpful mathematical functions.
Many a time I had to select a different behaviour based on the type of a boxed object. The usual solution for this is an ugly stream of if statements that check for the type and then return if found. A while ago I was writing about the dynamic keyword and how it can be used to declare a method for each specific type that is then executed from a simple method having the boxed object as a parameter. Some people liked it, some did not. What would have been nice is a switch statement that works with types, something like:
switch(obj.GetType()) { casetypeof(MyClass1): // do something with obj break; casetypeof(MyClass2): // do something else with obj break; default: thrownew NotSupportedException(); }
Alas, this is impossible in C# due to the fact that typeof(class) is not considered a constant, but a method call.
What I am about to present to you is in no way a best practice, but something that I've cropped up in my wild musings on code: why not use the try/catch blocks as a switch statement? The idea is simple: create a generic Exception class then throw it based on the type of the object, then catch the specific generic Exception class. Here is the code, enjoy:
So there is the simple class TypeCatchBlockException that has a Throw method. You have the dynamic implementation as well as the reflection implementation in the commented region. You execute Throw with an object inside a try block and then you add a catch block for each generic version of the exception for each supported type. The last block is reached if none of the supported types were encapsulated into the exception object.
Executing the console application in the code block results in:
Update: Some people didn't understand this was mostly a joke, so I needed to clarify it. We do need type switches and someone should implement them as a language construct. Throwing exceptions is expensive and the solution in this blog post would not be recommended for any production software.
But here is a nice solution for type switching using lambda expressions: Switching on Types.
You may want to create an image from a Stream or from a file on the system. You would want to use the static methods Image.FromStream or Image.FromFile to do it. However, you soon realize that this would not work if you immediately dispose the stream. Also, trying to delete the file would result in a locked file error. Could it be that some reference of the stream or file is kept in the resulting Image object? The answer is yes.
Microsoft explains it like this: GDI+, and therefore the System.Drawing namespace, may defer the decoding of raw image bits until the bits are required by the image. Additionally, even after the image has been decoded, GDI+ may determine that it is more efficient to discard the memory for a large Bitmap and to re-decode later. Therefore, GDI+ must have access to the source bits for the image for the life of the Bitmap or the Image object. And they have a fix to this, here: Bitmap and Image constructor dependencies
As you can see in the link above, their solution is different from indexed versus non indexed images. You can determine if an image is indexed or not by looking at the PixelFormat property. Also, you need to do some pretty weird stuff in the indexed case and there is no code on the Microsoft page. So here is a helper class I've cropped up to get images from Stream, File or byte array without locking any of the original resources:
/// <summary> /// Helper for Image objects /// </summary> publicstaticclass ImageHelper { /// <summary> /// Get an image from a byte array /// </summary> /// <param name="iconBytes"></param> /// <returns></returns> publicstatic Image GetImageFromBytes(byte[] iconBytes) { if (iconBytes == null || iconBytes.Length == 0) returnnull; using (MemoryStream ms = new MemoryStream(iconBytes)) { try { return GetImageFromStream(ms); } catch { returnnull; } } }
/// <summary> /// Get an image from a file without locking the file /// </summary> /// <param name="fileName"></param> /// <returns></returns> publicstatic Image GetImageFromFile(string fileName) { try { using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { return GetImageFromStream(stream); } } catch { returnnull; } }
/// <summary> /// Determines if an image is indexed (with a color palette) /// </summary> /// <param name="image"></param> /// <returns></returns> publicstaticbool IsImageIndexed(Image image) { switch (image.PixelFormat) { case PixelFormat.Format1bppIndexed: case PixelFormat.Format4bppIndexed: case PixelFormat.Format8bppIndexed: case PixelFormat.Indexed: returntrue; } returnfalse; }
/// <summary> /// Get an image from stream without locking the stream /// </summary> /// <param name="stream"></param> /// <returns></returns> publicstatic Image GetImageFromStream(Stream stream) { try { using (var image = Image.FromStream(stream)) { var srcBitmap = image as Bitmap; var destBitmap = new Bitmap(image.Width, image.Height,image.PixelFormat); if (IsImageIndexed(image)&&srcBitmap!=null) { Rectangle srcArea = new Rectangle(0, 0, image.Width, image.Height); BitmapData srcData = srcBitmap.LockBits(srcArea, ImageLockMode.ReadOnly, image.PixelFormat); Rectangle destArea = new Rectangle(0, 0, image.Width, image.Height); BitmapData destData = destBitmap.LockBits(destArea, ImageLockMode.WriteOnly, image.PixelFormat);
If you are like me, you often google a .Net class and find it at MSDN. Also, since you want the page to load quickly and get you the information you need, you probably selected the Lightweight view on MSDN. If you haven't, you should :) Anyway, a problem with MSDN is that it shows you every possible member of the class, which is especially annoying with WPF classes as they inherit from FrameworkElement that has a gazillion events. Wouldn't it be great if one could hide the inherited members from an MSDN page?
At first I thought I would parse the content of each row and detect the (Inherited from string, but it appears it is even simpler: table row elements have a data attribute that (if the member is inherited) contains the word inherited. Probably someone at MSDN wanted to make the same thing as me, but forgot to implement it (at least on the lightweight view). The javascript is simple enough:
var trs=document.getElementsByTagName('tr'); var l=trs.length; for (var i=0; i<l; i++) { var tr=trs[i]; var data=tr.getAttribute('data'); if (!data||data.indexOf('inherited')==-1) continue; tr.style.display=tr.style.display=='none'?'':'none'; }
You probably wonder why I haven't used jQuery. It is because I want it to work in a javascript: url so I can put it in a bookmark! Just as with the Firebug bookmarkyou need to manually create a bookmark in the Favorites folder (or to add any page as a favorite, then edit its URL) in Internet Explorer or to simply add a bookmark in the browser in Chrome and Firefox and paste the one line script. To make it easier, I will write them both here. The content of the .url favorite file:
[DEFAULT] BASEURL=http://msdn.microsoft.com/en-us/library/ [InternetShortcut] URL=javascript:var trs=document.getElementsByTagName('tr');var l=trs.length;for (var i=0; i<l; i++) { var tr=trs[i]; var data=tr.getAttribute('data'); if (data&&data.indexOf('inherited')>-1) tr.style.display=tr.style.display=='none'?'':'none'; }; void(0); IDList= IconFile=http://msdn.microsoft.com/favicon.ico IconIndex=1 [{000214A0-0000-0000-C000-000000000046}] Prop3=19,2
and the javascript line to use in other browsers:
javascript:var trs=document.getElementsByTagName('tr');var l=trs.length;for (var i=0; i<l; i++) { var tr=trs[i]; var data=tr.getAttribute('data'); if (data&&data.indexOf('inherited')>-1) tr.style.display=tr.style.display=='none'?'':'none'; }; void(0);
It all started from a Sacha Barber post on CodeProject, enumerating ways in which one can use Aspect Oriented Programming to mark simple automatic properties so that they get compiled into fully fledged INotifyPropertyChanged properties, thus saving us the grief of repeating the same code over and over again in each property setter. The implementations there were good, but too complex, relying on third party libraries, some of them not even free. He completely ignored template generators like T4, but then again, that particular approach has a lot of issues associated with it, like having to either parse source files or somehow tap into the compiled assembly... before you compile it. However, this brought forth the idea that I could do this, maybe in some other way.
Enter Felice Pollano, with his article on CodeProject detailing a method of using CodeDom generation to create at runtime the INotifyPropertyChanged object from an already existing type. This is pretty slow, but only when first creating the type, so with a cache system it would be totally usable. I liked this approach better, but I noticed there were some errors in the generated code and when I tried changing the generating code I had to look at it for half an hour just to understand where to change it. Wouldn't it be better to use some sort of template that would be easy to edit and use it to generate the proxy type?
So this is my take on generating INotifyPropertyChanged classes dynamically, avoiding the repetitive plumbing in property setters. The library contains a template for the class and a separate template for the properties. The proxy type is being generated in memory from a string that is generated from the source type and the two templates. All in all, one class, two templates, three public methods and four static methods. As easy as 1,2,3,4 :) Here is the code:
As you can see, the code needs only a type that has public virtual properties in it and it will create a proxy that will inherit that class, implement INotifyPropertyChange and override each virtual property with a notifying one. The templates are so basic that I feel slightly embarrassed; I keep thinking if I should have created template entities that would stay in the same file. :) Here are the templates:
{usings}
namespace __generatedINotifyPropertyChanged
{
public class {className} : {baseClassName},INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
{properties}
private void OnPropertyChanged(string propertyName)
{
var handler=PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
public override {propertyType} {propertyName}
{
get { return base.{propertyName}; }
set {
if (!Equals(value,base.{propertyName})) {
base.{propertyName}=value;
OnPropertyChanged("{propertyName}");
}
}
}
Don't forget to save the templates as Embedded Resource in the assembly.
Update: At Sacha Barber's advice I took a look at the DynamicObject solution for the INotifyPropertyChanged code smell. The link he provided is OlliFromTor's CodeProject article Using DynamicObject to Implement General Proxy Classes. While this works a lot easier than with compiling generated code, it also has a major drawback: the proxy class does not inherit from the original object and so it can only be used as such, but only in dynamic scenarios. Otherwise, it seems to be a perfect solution for proxy scenarios, if you are willing to discard the type safety.
I restarted my computer and afterwards I could not access any of the local sites via IIS. The error message in the Application logs of the EventViewer was
Event Type: Error Event Source: ASP.NET 4.0.30319.0 Description: aspnet_wp.exe could not be started. The error code for the failure is C0000142. This error can be caused when the worker process account has insufficient rights to read the .NET Framework files. Please ensure that the .NET Framework is correctly installed and that the ACLs on the installation directory allow access to the configured account.
to no avail. I was about to curse and restart the computer again when I found this pretty little link: IIS doesn't start. Error code: C0000142. A solution is at the bottom, as the least voted answer: Go to Task Manager, kill explorer.exe, Run another explorer.exe. This starts IIS (aspnet_wp.exe under inetinfo.exe) correctly.
Update: It bugged me that I had to kill explorer.exe. First of all it is a manual solution, then it always messed with my system tray icons. So I searched a little more. Short story shorter, you need to edit machine.conf and replace <processModel autoConfig="true" /> with <processModel userName="system" password="AutoGenerate" />. That effectively makes ASP.Net work under the System account, not the default machine. It does indicate the issue is permission related, but I don't get exactly where and why it should work if I restart explorer.exe. As long as you don't mind running ASP.Net under the System account, this solution seems to solve it. Here is the long version.
Note: you can find the machine.config file in %windir%\Microsoft.NET\Framework\[framework version]\Config\machine.config.
When I first tried to do drag and drop in WPF I thought it would be something easy like DragAndDrop.IsDraggable="True". Boy,was I wrong! The mechanism for this has remained almost unchanged from the Windows Forms version. It is completely event driven and has nothing in the way of actual graphical feedback of what is going on except making the mouse cursor look different. If you want to do it using MVVM, you have another thing coming.
Disclaimer:Now, I have found a good solution for all the problems above, but the drag and drop behaviour is part of a larger framework that I have been working on and creating a separate project just for it might prove difficult. I mean, you want to show MVVM drag and drop, you should also have Views and ViewModels and base classes and helpers and everything. The solution, I guess, is to make separate articles for the main features in the framework, then present the project as a whole in the end. The framework itself is work in progress and untested in a real life project, so this might have to wait, as well. I will make sure, though, to put much code directly in this post.
Ok then, let's define the requirements of this system. We need:
A drag item
A drop target
Showing the target is being dragged
Showing the target can or cannot be dropped
Showing the item being dragged
Changing the appearance of the original dragged element while dragging
Changing the appearance of the drop target while dragging something over
Allowing for drag and drop between Windows
Allowing for drag and drop between applications
Changing an application that works but has no drag and drop in an easy and maintainable way
Using as simple a system as possible
Doing everything using the Model-View-ViewModel pattern
From these requirements we can form a basic idea of the way we would like this to work. First of all, we need the ability to mark any element as a drag item. Also, we need a container that can be marked as a drop target. We can do this using boolean IsDragSource and IsDropTarget Attached Properties; once set they will force a bind of the drag and drop events to some special handlers that would then direct decisions to ICommands.
As we are doing it in MVVM, we don't use the elements directly, but the data they represent, so we work with dragging and dropping commands using data objects. The classes responsible with the decisions for the drop permissions and actions should be in the ViewModel. We could, of course, link all events to commands, but that would be very cumbersome to use. Besides, we want it simple, we don't really want the user of the system to care about the drag and drop inner workings. Therefore, the solution is to change the IsDragSource and IsDropTarget to DragSource and DropTarget properties that accept objects of type IDragSource and IDropTarget containing all the methods needed for the events in question:
/// <summary> /// Holds the data of a dragged object in a drag-and-drop operation. /// </summary> publicinterface IDraggedData { /// <summary> /// A dictionary with the format as the key and the data in that format in the value /// </summary> IDictionary<string, object> Values { get; }
/// <summary> /// Optional object for additional information /// </summary> object Tag { get; } }
/// <summary> /// Business end of the drag source /// </summary> publicinterface IDragSource { /// <summary> /// Gets the supported drop effects. /// </summary> /// <param name="dataContext">The data context.</param> /// <returns></returns> DragEffects GetDragEffects(object dataContext);
/// <summary> /// Gets the data. /// </summary> /// <param name="dataContext">The data context.</param> /// <returns></returns> object GetData(object dataContext); }
/// <summary> /// Defines the handler object of a drop operation /// </summary> publicinterface IDropTarget { /// <summary> /// Gets the effects. /// </summary> /// <param name="dataObject">The data object.</param> /// <returns></returns> DragEffects GetDropEffects(IDraggedData dataObject);
/// <summary> /// Drops the specified data object /// </summary> /// <param name="dataObject">The data object.</param> void Drop(IDraggedData dataObject); }
We need the methods for the effects to instruct the system about the types of operations that are allowed during drag and drop: None, Copy, Move, Scroll, All.
If you are going for the purist approach, you should use your own DragEffects enumeration, as above, since the DragDropEffects enumeration is in the System.Windows assembly, which in theory should have nothing to do with the ViewModel part of the application (one could want to use the ViewModel in a web environment, for example, or in a console application).
You will notice that the GetDropEffects method receives an IDraggedData object. This is also because the IDataObject interface and the DataObject class used in Windows drag and drop operations are also in the System.Windows assembly.
The IDraggedData interface is basically a dictionary that uses the data format as the key and the dragged data object stored in that format as the value. An important fact is that, when trying to drag and drop between applications, you need that the dragged data object be binary serializable. If not, you will only get the expected result when dragging to the same application. Here is an implementation of the interface, complete with a totally lazy way of getting the data based on which type is more "important":
/// <summary> /// Holds data for a drag-and-drop operation /// </summary> publicclass DraggedData : IDraggedData { #region Instance fields
/// <summary> /// A dictionary with the format as the key and the data in that format in the value /// </summary> /// <value></value> public Dictionary<string, object> Values { get { if (mValues == null) { mValues = new Dictionary<string, object>(); } return mValues; } }
/// <summary> /// A dictionary with the format as the key and the data in that format in the value /// </summary> /// <value></value> IDictionary<string, object> IDraggedData.Values { get { return Values; } }
/// <summary> /// Optional object for additional information /// </summary> /// <value></value> publicobject Tag { get; set; }
/// <summary> /// A dictionary for exceptions when retrieving the data in a specified format /// </summary> /// <value>The exceptions.</value> public Dictionary<string, Exception> Exceptions { get { if (mExceptions == null) { mExceptions = new Dictionary<string, Exception>(); } return mExceptions; } }
#endregion }
In the IDragSource interface we need the GetData method to extract the data object associated with a dragged object, since the Windows drag and drop mechanism encapsulates the objects in an application agnostic way, so one can perform drag and drop between applications or to/from the operating system. Finally, we need the Drop method in the IDropTarget interface to handle in the ViewModel what happends when an item is dropped.
Let's get to the juicy part: a DragService static class that will register the attached properties that we need. Besides the DragSource and DropTarget properties we need status properties like DragOverStatus (for the target), DraggedStatus and IsDragged (for the original dragged item) as well as two properties called BringIntoViewOnDrag and ActivateOnDrag which would bring an item completely into view or activate it (if a Window) when a valid drop target. This one is long. It also contains some extension methods that would be explained later.
Most of the code here is self explanatory: you have attached property that bind to the element drag and drop events and handle them either through direct code or by delegating to the values set. There are some extension methods like ExecuteWhenLoaded and ExecuteWhenUnloaded which execute an action when the element has finished loading or when it is unloading. An important aspect here is that a window closing does not trigger the Unloaded event for its child elements, so you need to bind to the Dispatcher.StartedShutdown event as well:
That is pretty much it for the drag and drop itself. You can implement IDropTarget on the ViewModel directly, but IDragSource needs to be binary serializable if you intend to drag and drop across application domains, so you usually implement it into a separate class that is a property of the dragged item view model or DataContext.
Because the DragService sets the status properties for each element, you can manipulate the appearance and behaviour of both drag source and drop target based on them. However, at this point the mouse will be the only indication that you are dragging something. You might want to actually drag something, especially since in a move operation the original element would be hidden during the drag. The problem here is that the drag source element cannot control the display of the dragged item in other applications, nor should it in its application, since it is not its responsibility. The solution: decorate an element over which you would drag something (like the root element of the entire window) with something that knows how to display dragged items:
This code uses an adorner to display the dragged item over it. Nothing fancy, since the actual template for the dragged data is defined in the decorator as the content. This is not the place to discuss the adorner, though, so here is just the code:
You would only need to decorate a view and then define the AdornerContent property for the decorator and, optionally, the grab point offset for the dragged element.
All that is left here is to show some usage examples. Let's assume we need a View over which we can drag and drop items:
Here you have a user control view which has the drop target set to its own view model and it is set to update the DragOverStatus property of the ViewModel when its attached DragOverStatus property is changed. The status properties are inheritable, so all the children of the view have them set. It is easy to define a Button style that has its text bolded when a copy operation is allowed for a drop item:
The container for the items is a simple WrapPanel and it is placed in a dock panel together with add and remove item buttons. This dock panel is decorated as a drag visual container, and the content that is dragged is set to a custom control called ContentItem, with a drag point set to 40,40. The DataContext property of the item is set to the DraggedData property so that it expresses the actual dragged object.
Now we have set up a container to be a drop target for items. It displays the items as they are dragged over it. All we have left is to set up the items, the ContentItem control, to be a DragSource:
The control style defines as a drag source the DragSource property of the data context of the item and synchronizes with the data context the properties of IsDragged and DragStatus. Triggers then make is pinkish when dragged and greenish when it can be dropped. Notice that this applies to the original item, while its representation is dragged, so you have a feedback of what is going on with the item right at the source.
I won't put here the ViewModels or the data items, since they are pretty much part of the business context, not the drag and drop. Just return DragEffects. All on the effects methods and you can drag anything anywhere, for example.
That's it, folks: drag and drop completely MVVM, without as much as writing an event handler or caring about the actual elements in the viewmodel. It would be even easier if you would allow references to WPF assemblies in the ViewModels, since you could also get the source elements and do stuff with them, but that wouldn't be much of an MVVM pattern, would it?
And here is the AdornerBase class, just a simple helper class:
/// <summary> /// Basic adorner class that exposes simple Attach and Dettach methods /// </summary> publicabstractclass AdornerBase : Adorner { #region Instance fields
privatebool mIsDettached;
#endregion
#region Properties
publicbool IsDettached { get { return mIsDettached; } }
public AdornerLayer AdornerLayer { get; private set; }
I will start with the errors. I was trying to access a site using a simple WebRequest.Create(url) method and a System.Configuration.ConfigurationErrorsException was thrown, with the message Error creating the Web Proxy specified in the 'system.net/defaultProxy' configuration section. That was weird, since I was doing it all from a WPF application and I had never had to modify the configuration for it to work. The exception had an even crazier inner exception: System.Runtime.InteropServices.SEHExceptionExternal component has thrown an exception. Google failed to provide a satisfactory answer to any of the errors, although there were quite a few people having the same problem.
I proceeded in creating a system.net/defaultProxy section in the app.config. I changed the True values of the proxy element to False:
Voila! No more errors in Create... exceptions would be thrownm however, by the GetResponse() method later on. This time no configuration exception, only the weird SEHException with the oh so helpful ErrorCode -2147467259 (0x80004005) which means "Unspecified Error".
I tried different stuff like resetting IIS, trying to decompile .Net assemblies and see where the error comes from (all to no avail since the error comes from a native Windows component. In my desperation I issued a "netsh winsock reset" in the command line and then restarted the computer. Frankly, I don't know if the command did it or just the restart. The fact is, it just worked afterwards.
So, here is the first exception:
System.Configuration.ConfigurationErrorsException occurred Message=Error creating the Web Proxy specified in the 'system.net/defaultProxy' configuration section. Source=System BareMessage=Error creating the Web Proxy specified in the 'system.net/defaultProxy' configuration section. Line=0 StackTrace: at System.Net.Configuration.DefaultProxySectionInternal.GetSection() at System.Net.WebRequest.get_InternalDefaultWebProxy() at System.Net.HttpWebRequest..ctor(Uri uri, ServicePoint servicePoint) at System.Net.HttpRequestCreator.Create(Uri Uri) at System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase) at System.Net.WebRequest.Create(String requestUriString) InnerException: System.Runtime.InteropServices.SEHException Message=External component has thrown an exception. Source=System ErrorCode=-2147467259 (0x80004005) StackTrace: at System.Net.UnsafeNclNativeMethods.OSSOCK.WSASocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, IntPtr protocolInfo, UInt32 group, SocketConstructorFlags flags) at System.Net.Sockets.Socket.InitializeSockets() at System.Net.NetworkAddressChangePolled..ctor() at System.Net.AutoWebProxyScriptEngine.AutoDetector.Initialize() at System.Net.AutoWebProxyScriptEngine.AutoDetector.get_CurrentAutoDetector() at System.Net.AutoWebProxyScriptEngine..ctor(WebProxy proxy, Boolean useRegistry) at System.Net.WebProxy.UnsafeUpdateFromRegistry() at System.Net.WebProxy..ctor(Boolean enableAutoproxy)
and here is the second:
System.Runtime.InteropServices.SEHException occurred Message=External component has thrown an exception. Source=System ErrorCode=-2147467259 StackTrace: at System.Net.UnsafeNclNativeMethods.OSSOCK.WSASocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, IntPtr protocolInfo, UInt32 group, SocketConstructorFlags flags) at System.Net.Sockets.Socket.InitializeSockets() at System.Net.IPAddress.InternalParse(String ipString, Boolean tryParse) at System.Net.NetworkInformation.IpAddrString.ToIPAddressCollection() at System.Net.NetworkInformation.SystemIPGlobalProperties.GetFixedInfo() at System.Net.NetworkInformation.SystemIPGlobalProperties.get_FixedInfo() at System.Net.NetworkInformation.SystemIPGlobalProperties.get_HostName() at System.Net.NclUtilities.GuessWhetherHostIsLoopback(String host) at System.Net.ServicePoint.get_ConnectionLimit() at System.Net.ConnectionGroup..ctor(ServicePoint servicePoint, String connName) at System.Net.ServicePoint.FindConnectionGroup(String connName, Boolean dontCreate) at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connName) at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint) at System.Net.HttpWebRequest.GetResponse()
.
The solution? Restart the computer. I wish I had a better, more informed answer, on why this happened, but I do not. I welcome any further explanation on the issue and I hope this helps people not waste a few hours like I did.
The scenario is as follows: you want to attach a collection to an element and fill it via XAML. The objects that you add to the collection should inherit the element DataContext.
One issue arising is that if you use an attached property for a collection you cannot use a default value in the metadata (since it would be used for all the instances of the property) and that if you don't instantiate it, any attempt to add stuff to it via the markup will result in a collection null exception. If this were a mere dependency property from inside the control, the solution would have been to create the collection in the element constructor. Since it is an attached one, we don't have this mechanism available.
Another solution would be to instantiate it in the property getter, like a normal property with a backing field, but in the case of XAML, the dependency and attached properties are accessed directly via the DependencyObject.GetValue method, bypassing the parent class property getter entirely. The only solution to force going through the getter is to register the attached property with a name string that is different from the convention.
Above we are registering an attached property of type ObservableCollection<MyItem> ingeniously named MyAttachedCollection from a class named ParentClass. The convention says we whould register it using a name that is the DependencyProperty name without the ending "Property". I, however, have added an "Internal" string, which forces the property system to go through the getter! Here is the getter:
Voila! This allows you to instantiate in the getter the troublesome collection.
Now, the other request in the scenario is to inherit the DataContext from the element the collection is attached to. To do that we at least need that the collection and the items in it to be DependencyObjects in order to have a DataContext, but we are going even further: we need to define them as Freezable! The Freezable abstract class requires you to implement a CreateInstanceCore method. Just make the MyItem class inherit Freezable and throw a NotImplementedException in the CreateInstanceCore method. For the collection itself, we need to inherit from another useful class: FreezableCollection<T>. After replacing ObservableCollection with FreezableCollection, the collection and the items have the same DataContext property as the element the property is attached to. An interesting fact here is that Freezable does NOT inherit from FrameworkElement, but it is a DependencyObject and the DataContext property does propagate down through the element tree.
One last interesting thing: the FreezableCollection class implements INotifyCollectionChanged, but explicitly! In order to use the CollectionChanged event you need to cast it in code to INotifyCollectionChanged.
Before you go on, let me summarize this long post for you: while it is possible to clone a control template in order to change just some things in it, it is a difficult and error prone process. The code at the end of the post is a proof of concept thing, which works for simple scenarios, but needs additional work for complicated controls.
I was exploring the option of not overwriting the ControlTemplate of a WPF Control when I try adding stuff to it. Instead, I tried to get the ControlTemplate and manipulate it before putting it back. It is not as easy as it seems. Even more, people stack over each other to advise everybody not to do it. I am not saying it is an easy option, so my advice is to try other alternatives, if you have them, but the idea is: it can be done!
Let's take it step by step. In order to get the control template we should get it as soon as it is available, but perhaps before applying it. One could override OnApplyTemplate and do it there or, as it is my case (trying to do it via attached properties and lacking an ApplyingTemplate event), do it once when the control is initializing. The control template is easily obtained via the Template property. If you try to change anything in it, though, you will get an exception, because the template is sealed. So the only option is to clone it, change stuff in it, then set the control template to that clone.
The template is of type ControlTemplate, but it doesn't seem to contain much. It has Resources and Triggers properties, also a VisualTree property and a LoadContent method. There is also a Template property in the ControlTemplate class... try to set it and a null exception will be thrown, so forget it. The first two are easy to use, just iterate through the collections. VisualTree is of the weird and undocumented type FrameworkElementFactory, while LoadContent is a method that returns a DependencyObject.
Well, the idea is that LoadContent will return the content of the template which you should use to set the VisualTree property, but the process of getting a DependencyObject and getting a FrameworkElementFactory tree is not simple.
First things first: get a new ControlTemplate. Its contructor gets a Type parameter which we take from the TargetType property of the original template. We then add any resources from the original template to the resources of the new one. Next step is to take the content, using LoadContent, which will get us the first child of the element tree. In order to traverse it we will use the VisualTreeHelper static class which exposes the GetChildrenCount and GetChild methods.
The next step is to create a FrameworkElementFactory. It has a constructor which receives a Type and another which gets a Type and a name string. We will use the first, since the Name can be set afterwards. The type we get from the type of the DependencyObject returned by LoadContent. The VisualTree of the new control template will have to be this new factory object, but it also needs all the properties of the original object as well as all its children.
In order to get the dependency and attached properties of each element we will use the MarkupWriter.GetMarkupObjectFor method, which returns a MarkupObject. Each of its Properties will have a DependencyProperty property which will give us the properties. However, the value of the property is not so easy to get. If we use GetValue, any binding or markup extensions will be evaluated and probably give wrong results (since the control has not been initialized yet). Using ReadLocalValue brings us pretty close, only that for certain objects like Binding we don't get a BindingBase object, but a BindingExpressionBase. We need to cast the value we get to BindingExpressionBase and TemplateBindingExpression and get to the underlying binding object.
Now that we've got the properties and the correct values, we use the factory SetValue method to set it. A special case is Name which must be set directly to the Name property. We use AppendChild to add a factory to a parent factory.
The last step is to get the Triggers from the original template and copy it in the new one. Now Seal it and you have yourself a clone. Not sure how one would manipulate the template to get a usable and maintainable template manipulation, but this is how you start.
I know you are suckers for code, so here it is:
Update:Actually the collapsed code below doesn't work except for the simplest of templates. There are several reasons for it and I will explore them below.
The first problem I found was dependency properties registered as read only that could only be set from XAML, like VisualStateManager.VisualStateGroups. When trying to use the FrameworkElementFactory SetValue method it would throw an error. Funny enough, the only reason that happened is because said method is checking if the property is read only and throws an exception. I had to use reflection to circumvent this, and it worked, albeit really ugly.
The second problem was more basic. Not every property is a dependency property. Such a simple property is Grid.ColumnDefinitions! Not only it is not a dependency property, but it is also read only. So I had to find another mechanism to fix this. At this point you probably realise this method is not a good one to employ, but if you are really desperate (or stubborn, like me) there is a way. The solution I found is to save all the properties that I need to set into a list and then set them in a RoutedEventHandler invoked from the Loaded event!
And if this is not enough, simply setting the value from the template in the control doesn't always work. In the generated template control the ColumnDefinition objects are already in the ColumnDefinitionCollection of the control. Adding them to a control that the factory generates results in an error. What I did here is a simple value=XamlReader.Parse(XamlWriter.Save(value)).
In other cases, like the Border.Child property, it must be completely ignored! So a list of properties to be ignored is needed.
Conclusion: Some improvements have been done in the code, but it's a little larger than before. The complicated way in which this works makes it cumbersome to be used, and I would not recommend it, but it works and it has extension points where errors with properties can be handled. Here is the new code:
#region Using directives
using System.Collections.Generic; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Markup;
#endregion
namespace BestPractices { /// <summary> /// Base class for ControlTemplate transforming classes /// </summary> publicabstractclass BaseTemplateTransformer : BaseControlTransformer { #region Public Methods
/// <summary> /// Clones the ControlTemplate of a control and allows for its manipulation /// </summary> /// <param name="control"></param> publicoverridevoid Transform(Control control) { ControlTemplate template = control.Template; if (template == null) { return; } // create new template ControlTemplate newTemplate = new ControlTemplate(template.TargetType); // copy the resources foreach (object key in template.Resources.Keys) { newTemplate.Resources.Add(key, template.Resources[key]); } //get the VisualTree factory from the original template content DependencyObject content = template.LoadContent(); newTemplate.VisualTree = OnGetElementFactory(content); // copy the triggers foreach (TriggerBase trigger in template.Triggers) { newTemplate.Triggers.Add(trigger); } // allow for template manipulation OnBeforeSeal(newTemplate); // seal the template and set it back newTemplate.Seal(); control.Template = newTemplate; }
/// <summary> /// Creates a custom ControlTransformFactory for the content object. /// Override in order to replace elements in the initial template. /// </summary> /// <param name="content"></param> /// <returns></returns> publicvirtual ControlTransformFactory OnGetElementFactory(DependencyObject content) { if (content == null) { returnnull; } // use the object type ControlTransformFactory factory = new ControlTransformFactory(content, this); return factory; }
/// <summary> /// Returns a safe value for setting on the control /// </summary> /// <param name="item">The value from the template</param> /// <returns></returns> publicvirtualobject GetSafeValue(object item) { return getSafeValue((dynamic) item); }
/// <summary> /// Returns true if a property needs to be saved and set when the control loads. /// Defaults to false, except for ColumnDefinitions and RowDefinitions /// </summary> /// <param name="propertyDescriptor"></param> /// <returns></returns> publicvirtualbool MustSetProperty(PropertyDescriptor propertyDescriptor) { return sMustSetProperties.Contains(propertyDescriptor.Name); }
#endregion
#region Protected Methods
/// <summary> /// Allows for the manipulation of a control template /// </summary> /// <param name="newTemplate"></param> protectedvirtualvoid OnBeforeSeal(ControlTemplate newTemplate) { }
#endregion
#region Statics
privatestaticreadonly List<string> sMustSetProperties = new List<string> { "ColumnDefinitions", "RowDefinitions" };
/// <summary> /// Transforms a DependencyObject tree into a FrameworkElementFactory tree /// </summary> /// <param name="content"></param> /// <returns></returns> publicstatic ControlTransformFactory CreateElementFactory(DependencyObject content) { if (content == null) { returnnull; } // use the object type ControlTransformFactory factory = new ControlTransformFactory(content); return factory; }
/// <summary> /// default return the same value /// </summary> /// <param name="value"></param> /// <returns></returns> privatestaticobject getSafeValue(objectvalue) { returnvalue; }
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Reflection; using System.Windows; using System.Windows.Markup.Primitives; using System.Windows.Media;
#endregion
namespace BestPractices { /// <summary> /// FrameworkElementFactory used in control template transformers /// </summary> publicclass ControlTransformFactory : FrameworkElementFactory { #region Nested
/// <summary> /// List of non dependency properties that will be set when the control loads /// </summary> protected List<MarkupProperty> SimpleProperties { get { if (mSimpleProperties == null) { mSimpleProperties = new List<MarkupProperty>(); } return mSimpleProperties; } }
#endregion
#region Constructors
public ControlTransformFactory(DependencyObject content, BaseTemplateTransformer templateTransformer = null) : base(content.GetType()) { mTemplateTransformer = templateTransformer ?? new NoTemplateTransformer(); // set its name string name = content.GetValue(FrameworkElement.NameProperty) asstring; if (!string.IsNullOrWhiteSpace(name)) { Name = name; } // copy the properties foreach (MarkupProperty propertyItem in getProperties(content)) { SetProperty(propertyItem); } // do it recursively int count = VisualTreeHelper.GetChildrenCount(content); for (int i = 0; i < count; i++) { DependencyObject child = VisualTreeHelper.GetChild(content, i); AppendChild(mTemplateTransformer.OnGetElementFactory(child)); } }
#endregion
#region Public Methods
/// <summary> /// SetValue that uses reflection to force DependencyProperties that were registered as read only /// </summary> /// <param name="dependencyProperty"></param> /// <param name="value"></param> /// <param name="forceSetReadOnly"></param> publicvoid SetValue(DependencyProperty dependencyProperty, objectvalue, bool forceSetReadOnly = false) { if (!forceSetReadOnly) { base.SetValue(dependencyProperty, value); } else { forceSetValue(dependencyProperty, value); } }
/// <summary> /// Sets a value from a MarkupProperty object. /// Dependency properties will be set via SetValue and the others via a Loaded handler on the object /// </summary> /// <param name="propertyItem"></param> publicvoid SetProperty(MarkupProperty propertyItem) { DependencyProperty property = propertyItem.DependencyProperty; if (property == null) { setSimpleProperty(propertyItem); } else { objectvalue = propertyItem.Value; if (value == DependencyProperty.UnsetValue) { return; } SetValue(property, value, property.ReadOnly); } }
#endregion
#region Private Methods
/// <summary> /// Force set value in the factory, even if the property is ReadOnly /// </summary> /// <param name="dp"></param> /// <param name="value"></param> privatevoid forceSetValue(DependencyProperty dp, objectvalue) { object resourceKey = getResourceKey(value); if (resourceKey == null) { updatePropertyValueList(dp, valueis TemplateBindingExtension ? "TemplateBinding" : "Set", value); } else { updatePropertyValueList(dp, "Resource", value); } }
/// <summary> /// Set a property to have its value set at load time /// </summary> /// <param name="markupProperty"></param> privatevoid setSimpleProperty(MarkupProperty markupProperty) { if (markupProperty.PropertyDescriptor == null) { return; } if (!mTemplateTransformer.MustSetProperty(markupProperty.PropertyDescriptor)) { return; } SimpleProperties.Add(markupProperty); if (mLoadHandler == null) { mLoadHandler = new RoutedEventHandler(simplePropertyHandler); AddHandler(FrameworkElement.LoadedEvent, mLoadHandler); } }
/// <summary> /// Handler on the Loaded event of the control /// </summary> /// <param name="sender"></param> /// <param name="args"></param> privatevoid simplePropertyHandler(object sender, RoutedEventArgs args) { foreach (MarkupProperty propertyItem in SimpleProperties) { PropertyDescriptor propertyDescriptor = propertyItem.PropertyDescriptor; if (propertyDescriptor == null || propertyItem.Value == null) { continue; } if (propertyDescriptor.IsReadOnly) { IList list = propertyItem.Value as IList; if (list != null) { IList destinationList = propertyDescriptor.GetValue(sender) as IList; if (destinationList != null) { foreach (object item in list) { destinationList.Add(mTemplateTransformer.GetSafeValue(item)); } } else { //shouldn't happend } } else { // what now? } } else { propertyDescriptor.SetValue(sender, mTemplateTransformer.GetSafeValue(propertyItem.Value)); } } FrameworkElement element = (FrameworkElement) sender; element.RemoveHandler(FrameworkElement.LoadedEvent, mLoadHandler); }
#endregion
#region Statics
static ControlTransformFactory() { // Get the types and methods that will be used in Reflection scenarios sUpdatePropertyValueListProperty = typeof (FrameworkElementFactory).GetMethod("UpdatePropertyValueList", BindingFlags.NonPublic | BindingFlags.Instance); sPropertyValueTypeType = typeof (FrameworkElementFactory).Assembly.GetType("System.Windows.PropertyValueType"); }
privatestaticreadonly MethodInfo sUpdatePropertyValueListProperty; privatestaticreadonly Type sPropertyValueTypeType;
/// <summary> /// get the properties set on a DependencyObject /// </summary> /// <param name="content"></param> /// <returns></returns> privatestatic IEnumerable<MarkupProperty> getProperties(DependencyObject content) { MarkupObject markupObject = MarkupWriter.GetMarkupObjectFor(content); return markupObject.Properties; }
/// <summary> /// Get the ResourceKey property from an object, if it exists /// </summary> /// <param name="target"></param> /// <returns></returns> privatestaticobject getResourceKey(object target) { if (target == null) { returnnull; } Type type = target.GetType(); PropertyInfo property = type.GetProperty("ResourceKey"); if (property == null) { returnnull; } return property.GetValue(target, newobject[] {}); }
In order to programmatically load a .crx Chrome extension as an external extension, the ID of the extension is required. The algorithm for computing it is:
make a SHA256 hash of the public key embedded in the .crx file
take the first 128bits (16 bytes) and encode them in base16
use characters a-p instead of the customary 0-9,A-F
For this we need, obviously, the public key. Reading from the CRX Package Format page, we can determine we need a 4 byte (Int32) value of the public key length and the public key itself. The length is found at position 8 in the file, the public key starts at position 16. Here is the code:
privatevoid checkPath(string path) { mUri = ExtensionHelper.GetUri(path); if (mUri == null) { thrownew Exception(string.Format("Parameter is not a valid URI ({0})", mPath)); } mPath = mUri.AbsolutePath; if (!mUri.IsFile && !mUri.IsUnc) { thrownew Exception(string.Format("Only file and local network paths are acceptable ({0})", mPath)); } DirectoryInfo di = new DirectoryInfo(mPath); if (di.Exists) { thrownew Exception(string.Format( "Loading extensions from folders is not implemented ({0})", mPath)); } FileInfo fi = new FileInfo(mPath); if (!fi.Exists) { thrownew Exception(string.Format("The file does not exist ({0})", mPath)); } if (fi.Extension.ToLower() != ".crx") { thrownew Exception(string.Format("The file extension must be a .crx file ({0})", mPath)); } try { mExtractor = getExtractor(fi); if (mExtractor.Check()) { return; } } catch (Exception ex) { thrownew Exception( string.Format("The file could not be read as a valid .crx file ({0})", mPath), ex); } thrownew Exception(string.Format("The file could not be read as a valid .crx file ({0})", mPath)); }
I was trying to verify an SHA256 signature (don't ask) and so I had to use the class SHA256CryptoServiceProvider. Alas, the constructor promptly threw an exception telling me the class is not supported on my system. I googled it and found this answer: C# - SHA256CryptoServiceProvider and related possible to use on WinXP?. Whereas the link reports this is a bug in .NET 3.5 I am working with version 4.0 and it is still there.
Apparently, the constructor of SHA256CryptoServiceProvider looks for a certain name in the cryptography providers installed on the machine. It looks for "Microsoft Enhanced RSA and AES Cryptographic Provider" and it gets the XP variant "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)". The solution is to export the key, remove "(Prototype)" and install the resulting reg file. Then it works. Here is the file, as it resulted on my computer:
I had this control that consisted of a textbox and a squigly red line in case of a required value error. In order to do it, I added the textbox and the line to a Grid, without specifying column or row values, so that the line would come above the textbox. It all worked well until I wanted to make the control align to the left, thus growing with the content entered in it. To my surprise, the control would stretch to the content width when in edit mode and go to 202 pixels outside it. The only things in the template were a textbox and a line inside a grid and a border, so I proceeded on inspecting all of their attributes in search for the culprit. It so happens that the Line was it!
Update: The Microsoft guys responded in a day to my bug report, but they couldn't reproduce it. It seems this behavior can be reproduced only in a Grid column with Width="Auto". Frankly, I was a bit surprised to see that, lacking that grid column, a line with Stretch="Fill" and HorizontalAlignment to "Left" would still expand the container to its maximum size. End update. The code looked like this:
As you can see, the line is Left aligned, it has no specified Width, the only giveaway is the Stretch property set to Fill. Now, you think that was the problem, but it was not! See that I have a MaxWidth of 200. That was per request.
It appears that if I remove the MaxWidth setting, the line goes DOWN to the normal size of the parent inner width. MaxWidth, not MinWidth, mind you. Ok, so I've tried some other things. Stretch to None makes the line be 1px long. Setting X2 to 200 makes the line take 200px, same as setting Width. HorizontalAlignment to Stretch makes the line go to the center of the space if it is bigger than the 200 MaxWidth.
The solution? I've bound the Width of the line to the ActualWidth of the TextBlock above. Another option would have been to surround the line with a scrollviewer or some other control that would allow the line to be as long as it wanted without showing a scrollbar or stretching to the size of its content. Either solution seems bad.
Is this a bug? I think so. If the Stretch property should have affected the space the line takes, then it should have done so when MaxWidth was set to Infinity, but it did not. Well, hopes it helps someone. Final code piece for the line:
Update: The fix I've exemplified above doesn't work when the HorizontalAlignment of the grid is Stretch or has a Width and the TextBox doesn't have a Left HorizontalAlignment. I have tried to replace the Line with a ScrollViewer with hidden scrolling on the horizontal and disabled on the vertical and having a MaxWidth of 200, Inside placing the troublesome Line. I've tried all kinds of panels and combinations of HorizontalAlignment, HorizontalContentAlignment, ClipToBounds, etc. All to no avail.
Finally, the solution was to create a simple control that would ignore the dimensions of the child controls, demanding no space. I named it ClipContainer and here is its source:
Sometimes, when working with a WPF application, Snoop would crash with the most innovative error messages possible. One of these was 'Object' type does not have a matching DependencyObjectType. Well, of course it doesn't, but where does this come from, why only when I use Snoop and how do I fix it?
I won't bore you with the details, enough said I have traced the problem to an AttachedPropertyBrowsableForTypeAttribute I have used on an attached property. I was using a Resharper Live Template (a snippet) to generate the code for the property and I'd accidentally forgot to set a proper type in the attribute and left the default object.
I had this container that I wanted to handle any mouse click events. So I proceeded on creating an attached property that has a property changed callback in which I would take the element and add a mouse handler to it. Pretty standard stuff, only it didn't quite work. It also blocked any events in the children. As I knew this should have happened in Preview events, not in normal events, I was stumped.
The problem: the attached property was defined with FrameworkPropertyMetadataOptions.Inherits which meant its value applied to all the children, meaning the value changes on all children when I set it on the parent. That meant the handler for the mouse click events was attached to the container and each of its descendants.