I want to save form position. I have successfully set Form.Location property in ApplicationSettings->PropertyBinding but Form.Size is not listed in property binding list. Why? Do I need to add this property to save properties list using code?
The Form class overrides the Size property to prevent it from getting saved. This is by design, it uses the ClientSize instead so that the size doesn't depend on the border width chosen by the user. You'll find ClientSize in the property binding list.
This is still not a good idea, you don't want to save the size if the window is minimized or maximized. It will not restore properly. Instead, override the OnResizeEnd() method and only save the size if the WindowState is Normal.
Related
What I want to do is intercept assignments to the Text property on my control inherited from a TextBox. I the want to modify this text and have the modified text shown in the text box. I aslo need the ability to return something different from what is shown in the text box when the property is read. In Win Forms I could do this by overriding the Text property as it was declared virtual. Obviously things are a bit different with dependency properties. One idea I had was to use OverridePropertyMetadata to have my own callback detect the property change and then call the original callback obtained with GetMetadata. This doesn’t work as property changed callbacks are merged. I’d be interested if there is another way to do it which is specific to this property but I like to find out if it is possible “override” dependency properties in general.
My application is a formatted text box when the text is set to 1000 say (for a numeric format), the text box shows 1,000 but when you read the text you get back 1000 again- the box will keep track of the un formatted text internally. I managed to implement in Win Forms fairly easily but am now trying to port it to WPF.
I think OverridePropertyMetadata is the way to go, but rather than defining a new PropertyChangedCallback, you could write a new CorceValueCallback:
static object CoerceText(DependencyObject d, object baseValue)
{
string s = (string)baseValue;
// Change s to whatever you want
...
return s;
}
I am having a number of controls in my application(which user can add to canvas), each having various properties(mostly dependency properties). User can change its properties through property grid(like color, text etc.).
I have save functionality implemented, so if user makes any change in canvas we ask him to save the document before leaving. At present I am keeping track of Add/Delete/Resize like operations(changing IsChanged flag to true). I also want to keep track of any property changes done by user, say if he changes the color of control through propertygrid.
One straightforward solution is to handle PropertyChangedCallback for each proeprty and set the flag in that. Problem with this is that I will have to write PropertyChangedCallback for each proeprty in each control, and at the same time I will have to make sure that every new proeprty added do the same.
My question: Is there any other better way of tracking property changes, say at some global place?
If your objects/classes are DependencyObjects, you could create your own 'base class', deriving from DependencyObject which overrides OnPropertyChanged:
http://msdn.microsoft.com/en-us/library/system.windows.dependencyobject.onpropertychanged.aspx
In the implementation you could register that the object had changed in some singleton or associated change-tracking manager class, then call base.OnPropertyChanged.
Then change all your objects to implement this new class rather than DependencyObject and when any properties change your code will get called.
Hope that helps!
I have a childwindow with a number of Textboxes, Comboboxes, and DatePickers. I want to know if a user has changed any value in these (to know if I need to save to db)
One way I could think of doing this are in the 'on chg' event handlers and set bool. But if a user changes the value, in say a combobox, then changes back to the original this would still be seen as a change.
Are there other alternatives?
(note the project is not set up as MVVM)
If you don't use mvvm but still bind to an object then:
before the window is shown create a copy of the object, save it, and bind it to DataContext
whenever you need to know if user made any changes you can compare the saved object to DataContext (property by property)
I you don't use binding at all then:
before the window is shown save all fields that can be modified to a Dictionary
whenever you need to know if user made any changes you can compare the dictionary values to values of the fields
I would like to let users resize my form but when they reach a specific size to disable this ability to make it smaller window than i want.
Any suggestions?
You can set the MinimumSize property of the form to the minimum size you want to enforce.
There is also a mirror property MaximumSize (mentioned for completeness).
Set the MinimumSize property on your form. This will prevent the user from making the form any smaller than this value. Similarly, you can set the MaximumSize property to ensure that they cannot make it any larger than that value.
Set the form's MinimumSize property in the designer.
Set the form's MinimumSize property to the smallest size you want to allow.
I populate a ListBox control with my own objects redefining ToString(). The objects are displayed correctly when I just add those objects using listBox1.Add(myObject). However, if I later change something in this object, no changes are displayed in the listbox. Debugging reveals that an object inside listBox1.Items is indeed changed, but it is not reflected on a screen.
Interestingly enough, if I reassign a particular listbox item to itself (sounds a bit weird, doesn't it?), like:
listBox1.Items[0] = listBox1.Items[0]
this line will display a correct value on screen.
What is going on here? Does it have anything to do with threading?
Since you're using ToString of the object to provide the text of the list box item, the ListBox has no idea that the value has changed. What you should do instead is have the object implement INotifyPropertyChanged then expose a public property such as Name or Text and return what you normally would have returned from ToString().
Then set the DisplayMember of the ListBox to the name of the new property.
Make sure you are correctly raising the PropertyChanged event in the object and the ListBox should be able to automatically pick up the changes.
Edit: Adrian's edit reminded me that I do believe you'll need to use a BindingList as your data source in order for the property change notifications to be picked up. A quick scan in Reflector looks like ListBox on its own will not pick up the property changes mentioned above. But INotifyPropertyChanged + BindingList should.
The ToString() value of each item is cached when the listbox is first displayed. If an item in the listbox's Items collection then changes, the listbox does not notice and still uses the cached ToString() values for display. To force the listbox to update, either call RefreshItems() to refresh all items, or call RefreshItem(int) specifying the index of the item to refresh.
From the MSDN docs for RefreshItems():
Refreshes all ListBox items and retrieves new strings for them.
EDIT: It turns out that both of these methods are protected, so cannot be called externally. In trying to find a solution, I came across this SO question that this question is basically a duplicate of.
Have you tried calling Refresh() on the ListBox? I think the problem is that the ListBox does not know your object changed. The reason reassigning the the item works is because the ListBox will repaint itself when the collection changes.
you could invalidate the control, forcing a re-paint... perhaps..