F# WPF set a member value of an object after the constructor - wpf

I was having this problem earlier, where when I would try to set the height of a WPF window, it would give me this error:
unexpected identifier in member definition
I found a workaround by setting all the members's values in the constructor.
My old code looked like this:
module UI=
type Display () =
let window = new Window()
window.Height <- 600
I got it to to work by doing this:
module UI=
type Display () =
let window = new Window(Height = 600.00, Width = 800.00)
But I can't help but wondering if there is some way to set the
height (or other members) AFTER calling the window constructor?
I say this because the . operator is incredibly useful to me, since I am still learning the .NET framework, I don't know all of the members of a particular class. I would rather use the . operator to browse its members and see if I missed anything than have to go to the MSDN online. Also, its harder to read if I have a lot of member values set in the constructor.
Do I need to declare the window as mutable?

Actually, after some careful research. I have found I needed a do binding.
as stated clearly on the MSDN here
A do binding appears together with or after let bindings but before member definitions in a class definition. Although the do keyword is optional for do bindings at the module level, it is not optional for do bindings in a class definition.
Even though they do not appear to be required for the class that has your main method, they are required for other classes.
module UI=
type Display () =
let window = new Window()
do window.Height <- 600.00
window.Width <- 800.00
Keep in mind that any other code that does execution must also be indented with the do, like the window.Width <- 800.00 is.

Related

Winforms ObjectListView: inner OLVColumn instances Name property is empty string so I cannot show/hide columns by name

This question is an offshoot of: Localizing ObjectListView OLVColumn, impossible due to Empty Name property
For simplicity's sake, let's say my ObjectListView contains car information. User A wants to display only Make and Model columns. User B only wants to display Model and Year columns. These preferences would be saved to/loaded from an .ini file on the users' local machines.
I cannot loop through the columns of the ObjectListView and do if (col.Name == colNameFromIni) { col.Visible == true; } because the .Name property of every column is an empty string ("") and does not get serialized to the designer codebehind file. This never happens with any other Winforms control (Label, Button, etc.) They always get their .Name written to the designer codebehind.
In some sense, this is a flaw in Winforms itself, because OLVColumn inherits from System.Windows.Forms.ColumnHeader, and a traditional ListView has exactly the same problem. .Name is always an empty string for all columns.
I would like to patch our local build of ObjectListView.dll to force populate the .Name property, but I can't figure out how Winforms automagically knows the name of every control on the form. It somehow(?) knows the names of the OLVColumn objects since it can display them in the Edit Columns... dialog on the ObjectListView's context menu. I'm also a little fuzzy on where the best spot is to plug this in.
(Yes, per linked question at top I know that as a last resort, I can hardcode colXX.Name = "colXX"; for all columns in my source code, but future column additions are likely to get overlooked and a programmatic solution is much preferred.)
(See also: https://sourceforge.net/p/objectlistview/bugs/160/ : the ObjectListView author declared this a wont-fix so it is up to me (or us), I guess.)
As you point out, this is a bug which is not with the ObjectListView, but the underlying component. And a bug which is around since at least 2008! Therefore, I doubt it will ever be fixed by MS.
Actually, it is a problem with the Autogenerated code in the designer.
If you look at other components such as a button, then the autogenerated code adds a name such as this;
//
// button2
//
this.button2.Location = new System.Drawing.Point(458, 199);
this.button2.Name = "button2";
...
But for ColumnHeader (Listview) and OLVColumn (ObjectListView), then this is not done, so then you end up with this.
//
// olvColumn1
//
this.olvColumn1.AspectName = "Name";
this.olvColumn1.Text = "Name";
If you manually add the line
this.olvColumn1.Text = "olvColumn1";
Then the "problem" is solved.
Of course, you can't do this, because the designer will override the autogenerated code when you make any changes, and then you will lose these manually added lines. It is also not sustainable.
So I'm afraid you need to code around this with some kind of ugly solution. Some options are:
Use the Tag to store the name and compare against this.
Use the text instead of the name (not possible if you have multi
language support!)
Code the names column manually in the Constructor
Set the Text to be something like "ColName;ColText" and then in your
code separate these out.
I have done option 3 in the past, but only I was maintaining the code, so this was easy.
What you could do to ensure you don't have discrepancies is to add a check in your constructor to compare the actual number of columns with the number you expect (hard coded for), and throw an exception if they don't match. Also, not the best, but another way to highlight and reduce errors.
The workaround for this is to get the OLVColumns via reflection and set their column's Name property at runtime. Every OLVColumn is a form-level field, so just pick them out of the list returned by GetFields().
Dim allFieldInfos As FieldInfo() = GetType(FrmMain).GetFields(BindingFlags.NonPublic or BindingFlags.Instance)
For Each fi As FieldInfo In allFieldInfos
If fi.FieldType Is GetType(OLVColumn) Then
Dim instance As OLVColumn = fi.GetValue(Me)
For Each col As OLVColumn In fdlvMain.AllColumns
If ReferenceEquals(col, instance) Then
col.Name = fi.Name
End If
Next
End If
Next

InvalidOperationException in Fsharp.Core.dll

So I am doing a simple personal project in winforms with F#. My code used to work, but now throws this exception for seemingly no reason.
An unhandled exception of type 'System.InvalidOperationException' occurred in FSharp.Core.dll
Additional information: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized.
The code is a member method that is being invoked from the constructor of the form itself
do
//lots of other constructor code before this point
// render the form
form.ResumeLayout(false)
form.PerformLayout()
form.ReloadGoals
//several other members before here
member form.ReloadGoals =
let x = 10 //crashes on this line
The website where I grabbed the template for the project I am using is this one.
Unfortunately I have made some substantial additions to this.
I would be glad to post more code, but I need to know what code would be relevant exactly, as I am not exactly sure and don't want to bog down the post in extraneous code.
Also I can't really find a lot of documentation on System.InvalidOperationException.
Every time I find it, it is being used as an example of an exception you can throw on your own, not what causes it.
See The F# 3.0 Language Specification (final version, PDF), §8.6.1 Primary Constructors in Classes:
During construction, no member on the type may be called before the last value or function definition in the type
has completed; such a call results in an InvalidOperationException.
Almost certainly, your code in the question doesn't tell the full story. If you hit the above
mentioned restriction, then there's somewhere an attempt to access a field or member not fully initialized.
Some example:
type X() as this =
let x = this.X
member __.X = 42
X()
One workaround might be to encapsulate the offending code in a member of its own and call that in the constructor instead. Another would be the wrapping in a function definition.
This will be an incomplete answer, since I cannot reproduce the problem (using F# interactive, the given example, the ReloadGoals modification, and Form.Show, the code runs fine). However, there are strange things happening:
Taken from the template, there should be a handler method for the Form.Load event, which fires when the type is fully constructed. Why is additional loading code in the constructor instead of this event handler? Load exists precisely to counter this kind of problem with unorderly initialization.
The template you are using isn't exactly sane F#. For example, initControls is a value of type unit that is evaluated where it is defined; its binding to a name is absolutely useless and should be replaced with a simple do. Writing initControls in the do block later has no effect at all. form.ResumeLayout(false); form.PerformLayout() should be equivalent to form.ResumeLayout(true), but I don't understand what these are doing in the constructor in the first place. The event handlers have two possibly unnecessary indirections: one to a delegate constructor, another to a method that has no real reason to exist -- the handlers should be lambdas or simple, private functions. Why are they public members?!
The error appearing in the question is probably caused by the usage of form in its own constructor. Move your new usage to the Load event handler, and it should work.
Personally, I would go further and ditch implementation inheritance by instantiating a plain Form and subscribing to its events. For example, in FSI, something similar to the template could be done like this:
open System.Drawing
open System.Windows.Forms
let form = new Form()
form.ClientSize <- new Size(600, 600)
form.Text <- "F# Form"
let formLabel = new Label()
formLabel.Text <- "Doubleclick test!"
formLabel.DoubleClick.Add <| fun _ -> form.Close()
form.Controls.Add(formLabel)
form.Show()
which uses no inheritance at all. (In an application, you'd use Application.Run etc instead of form.Show().) This does not run into initialization problems as easily and, additionally, is very useful if you want to encapsulate the form inside a simpler type or even just a function.

UICollectionViewLayout Examples

Can anybody point me in the right direction to how I could use UICollectionViewLayout to create an interface similar to the Pinterest column layout?
I tried searching online, but it looks like there are not many examples out there yet.
The 1000memories "Quilt" view is pinterest-like and open source: http://blog.1000memories.com/168-opensourcing-quilt, and you can dig through that to see how it works.
If you're looking for a more conceptual overview, here's the basic idea of what you're going to want to do. The easiest thing by far, if you just need a Pinterest-style layout, is to subclass UICollectionViewFlowLayout. You get a lot of layout help from this class, and Pinterest style is within its capabilities. You only need to override one method.
Set up a normal UICollectionView using UICollectionViewFlow layout. A quick way to do this is:
Drag a UIViewController onto a storyboard, drop a UICollectionView on that. Set the classes to match your custom classes, etc. You can use a delegate and create a delegate class here but strictly speaking that is not necessary to achieve JUST the Pinterest flow layout (you will almost definitely want to break the selection responsibility stuff into a delegate class in reality though).
Stub out a data source. Implementing the data source protocol for UICollectionView (http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewDataSource_protocol/Reference/Reference.html) is trivially simple. Make sure you set a reuse identifier on your UICollectionViewCell. You need:
(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
just return 1 for now;
(NSInteteger)collectionView:numberOfItemsInSection:
hardcode a number for now, make it 20.
– (UICollectionViewCell *)collectionView:cellForItemAtIndexPath:
This is one of the places where subclassing the flow layout's gonna do you a favor. All you really need to do here is call dequeueReusableCellWithReuseIdentifier:forIndexPath: with the index path. If you added a UIImageView or some labels to the cell, this would be a great place to actually assign the image, text, etc.
In the viewController's viewDidLoad instantiate a UICollectionViewFlowLayout and set the UICollectionView's datasource to yours and layout to flowlayout. Remember, this class is a subclass of UICollectionViewViewController.
self.collectionView.dataSource = [[YourDataSource alloc] init];
self.collectionView.collectionViewLayout = [[UICollectionViewFlowLayout alloc] init];
Ok. At this point you should be able to run your app and see some stuff on the screen. This is a whirlwind overview. If you need more details about how to set up ViewControllers and so on there's tons of stuff available about that.
Now comes the important part, Pinterest-izing the flow layout.
First, add a new class that is a subclass of UIViewControllerFlowLayout. Change your ViewController's viewDidLoad to instantiate this class and assign as the UICollectionView's collectionViewLayout.
The method you are going to need to implement is - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect.
Here's the thing: The superclass is going to do almost all the work for you. Your code is going to look something like this:
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
[attributes enumerateObjectsUsingBlock:^(id attr, NSUInteger idx, BOOL *stop) {
float newYCoord = [calculationMethodYouHaveToWriteFor:attr.frame];
attr.frame = CGRectMake(attr.frame.origin.x, newYCoord, attr.size.width, attr.size.height];
}];
}
Pinterest uses fixed-width columns, all you need to do in your calculation method is figure out what column you are in (`attr.origin.x / _columnWidth), and look up the total height in that column from the ivar you've been saving it in. Don't forget to add it to the new object's height and save it back for the next pass.
The flow layout superclass handles: making cells, determining which cells are visible, figuring out the contents size, figuring out the arrangement of the rows in the x direction, assigning index paths to cells. Lots of junk. And overriding that one method lets you fiddle with the y-pos to your heart's desire.
Heres two from github
https://github.com/jayslu/JSPintDemo
https://github.com/chiahsien/UICollectionViewWaterfallLayout
I've used a modified version of Waterfall in a project now, and I'm investigating JSPint now.
I have created a custom uicollectionviewlayout which is used in my personal project. Here is the link. Hope it helps.
https://github.com/johnny0614/YJZAlbumCollectionViewLayout
You can get anything you want from here:
https://github.com/ParsifalC/CPCollectionViewKit
For example(Both these two layouts are custom UICollectionViewLayout):

What is this method of element instantiation called?

Whenever I create a UIElement in code behind, I'd do something like this:
Button button = new Button();
button.Content = "Click Me!";
But then I saw this syntax somewhere, and wanted to know what it's called. I haven't ever seen it used in any of my .NET books:
Button button = new Button { Content="Click Me!" };
This is obviously nice because it's concise. So I guess my questions are:
what's it called?
are there any disadvantages to instantiating a UIElement in this manner?
I've also had trouble figuring out the right way to set properties like CornerRadius and StrokeThickness, and thought the answer to #1 might help me make more intelligent search queries.
1: An "object initializer"
2: Nope; it is very handy for code samples, in particular ;-p
Things you can't do in an object initializer:
subscribe events
combine with collection initializers on the same collection instance (an initializer is either an object initializer (sets properties) or a collection initializer (adds items)
You can get past these limitations by cheating:
Button btn;
Form form = new Form { Text = "Hi", Controls = { (btn = new Button()) }};
btn.Click += delegate { ... };
.Net 3.5 enhancement of Object Initializers, it is just a shorthand mechanism.
Object Initializer
It does the same thing under the hood. Second option uses a single line rather than two, which is nice & concise. .NET >= 3.5 only.
It's called an object initializer and it doesn't have any disadvantages.

How can I edit immutable objects in WPF without duplicating code?

We have lots of immutable value objects in our domain model, one example of this is a position, defined by a latitude, longitude & height.
/// <remarks>When I grow up I want to be an F# record.</remarks>
public class Position
{
public double Latitude
{
get;
private set;
}
// snip
public Position(double latitude, double longitude, double height)
{
Latitude = latitude;
// snip
}
}
The obvious way to allow editing of a position is to build a ViewModel which has getters and setters, as well as a ToPosition() method to extract the validated immutable position instance. While this solution would be ok, it would result in a lot of duplicated code, especially XAML.
The value objects in question consist of between three and five properties which are usually some variant of X, Y, Z & some auxiliary stuff. Given this, I had considered creating three ViewModels to handle the various possibilities, where each ViewModel would need to expose properties for the value of each property as well as a description to display for each label (eg. "Latitude").
Going further, it seems like I could simplify it to one general ViewModel that can deal with N properties and hook everything up using reflection. Something like a property grid, but for immutable objects. One issue with a property grid is that I want to be able to change the look so I can have labels and textboxes such as:
Latitude: [ 32 ] <- TextBox
Longitude: [ 115 ]
Height: [ 12 ]
Or put it in a DataGrid such as:
Latitude | Longitude | Height
32 115 12
So my question is:
Can you think of an elegant way to solve this problem? Are there any libraries that do this or articles about something similar?
I'm mainly looking for:
Code duplication to be minimized
Easy to add new value object types
Possible to extend with some kind of validation
Custom Type Descriptors could be used to solve this problem. Before you bind to a Position, your type descriptor could kick in, and provide get and set methods to temporarily build the values. When the changes are committed, it could build the immutable object.
It might look something like this:
DataContext = new Mutable(position,
dictionary => new Position(dictionary["lattitude"], ...)
);
Your bindings can still look like this:
<TextBox Text="{Binding Path=Lattitude}" />
Because the Mutable object will 'pretend' to have properties like Lattitude thanks to its TypeDescriptor.
Alternatively you might use a converter in your bindings and come up with some kind of convention.
Your Mutable class would take the current immutable object, and a Func<IDictionary, object> that allows you to create the new immutable object once editing completes. Your Mutable class would make use of the type descriptor, which would create PropertyDescriptors that create the new immutable object upon being set.
For an example of how to use type descriptors, see here:
http://www.paulstovell.com/editable-object-adapter
Edit: if you want to limit how often your immutable objects are created, you might also look at BindingGroups and IEditableObject, which your Mutable can also implement.
I found this old question while researching my possible options in the same situation. I figured I should update it in case anyone else stumbles on to it:
Another option (not available when Paul offered his solution since .Net 4 wasn't out yet) is to use the same strategy, but instead of implementing it using CustomTypeDescriptors, use a combination of generics, dynamic objects and reflection to achieve the same effect.
In this case, you define a class
class Mutable<ImmutableType> : DynamicObject
{
//...
}
It's constructor takes an instance of the immutable type and a delegate that constructs a new instance of it out of a dictionary, just like in Paul's answer. The difference here, however, is that you override the TryGetMember and TrySetMember to populate an internal dictionary that you're eventually going to use as the argument for the constructor-delegate. You use reflection in order to verify that the only properties that you're accepting are those that are actually implemented in ImmutableType.
Performance wise, I wager that Paul's answer is faster, and doesn't involve dynamic objects, which are known to put C# developers into fits. But the implementation for this solution is also a little simpler, because Type Descriptors are a bit arcane.
Here's the requested proof-of-concept / example implementation:
https://bitbucket.org/jwrush/mutable-generic-example
Can you think of an elegant way to solve this problem?
Honestly, you just dance around the problem, but don't mention the problem itself ;).
If I correctly guess your problem, then the combination of MultiBinding and IMultiValueConverter should do the trick.
HTH.
P.S. BTW, you have immutable class instances, not value objects. With value objects (which are described by struct keyword) you would dance much more no matter if there were setters or not :).

Resources