I have been working in .NET and WPF lately. Of course, I ran into some issues and had to look up some solutions. I wrote some of it down, for "future reference" and for anyone who might be interested.
Design Time Data and Properties
When designing WPF data template for ListBox items I wanted some preview in design time with sample mock data for the items. Also, some simple way to override certain property values would be nice (e.g. when you bound brushes of path to some run time values but want to use fixed ones for design). To use the mock data you can use d:DataContext
design time attribute. Some class with the sample data is created in code behind and then bound using this attribute.
public class MockMeasurementList { private MeasurementList measurements = new MeasurementList(); public MeasurementList Measurements { get { return measurements; } } public MockMeasurementList() { measurements.Add(new Measurement( new Position(49.3051356, 16.5607972, 358), new Vector(52.035075, 7.854967, 1492.690400)); } }
<UserControl.Resources> <mocks:MockMeasurementList x:Key="DesignList"/> </UserControl.Resources> <ListBox Name="ListMeasurements" d:DataContext="{Binding Source={StaticResource DesignList}}" ItemsSource="{Binding Measurements}">
WPF design time value for simple properties like brushes and sizes can be done for example using this approach of Marcin Najder. I use it for example for stroke and fill brushes of map markers:
<UserControl ... xmlns:dtools="clr-namespace:DesignTools"> ... <Path Stroke="{Binding Stroke}" Fill="{Binding Fill}" dtools:d.Stroke="Navy" dtools:d.Fill="PowderBlue"> ...
Events and Delegates Returning Bool
Suppose we have an event like this:
public event Func<bool> StoreMeasurementQuery;
and we want to do some action (e.g. store a measurement) only if all handlers subscribed to the event return true (Is the measurement valid? Is there enough storage?). Now if we raise the event the usual way (assuming StoreMeasurementQuery != null
):
bool store = StoreMeasurementQuery();
the result won't be as one could expect as store
will hold the return value of only the last handler executed. To get some sensible results we have to execute the handlers individually and check out their return values. Based on this SO answer I wrote two these extensions:
public static bool AllSubscribersReturnTrue(this Func<bool> evt) { return evt.GetInvocationList().Cast<Func<bool>>(). Select(func => func()).ToList().All(ret => ret); } public static bool AnySubscriberReturnsTrue(this Func<bool> evt) { return evt.GetInvocationList().Cast<Func<bool>>(). Select(func => func()).ToList().Any(ret => ret); }
to get logical AND and OR of all event handlers return values.
Grid Mouse Interaction
By default, Grid and other Panel controls don't receive mouse events. If you want to use Grid for example as clickable container for list box items, you need to set some background to it. Background="Transparent"
is good enough.