|
Funnily enough, you can get this behaviour without too much trouble. Basically you need to look into IEditableObject and IEditableCollectionView to add this functionality. I blogged about it here[^].
|
|
|
|
|
Not a good idea to re-invent the wheel here. You should stick with IEditableObject since that is the "standard" way of doing it. Doing it the "standard" way has the benefit of clean integration with controls.
|
|
|
|
|
Lots of problems with your solution:
1) reflection is slow
2) only supports public, simple properties... what about private and/or complex properties? what about nested properties?
3) reference objects will get set in both copies, no?
4) will not work with controls that require IEditableObject
|
|
|
|
|
Collin Jasnoch wrote: Soo how do you expect the IEditableObject to do this work??? (if you read Pete's
blog he even says that his EditableObject uses reflection....). Also reflection
is not that slow. I mean if this has to occur over and over (like 100's of time
in seconds.. why would this be though???) and the object is very large (consider
refactoring) you may want a different option (again.. I do not see how the
IEditableObject solves this.. it is merely an interface, NOT an implimentation
of it).
Are you familiar with how IEditableObject works? You just implement 3 standard methods any way you want. If I was doing it? Well, I'd have my base object implement ICloneable and use that to clone the object properly. That has the benefit of being another standard interface that other people might want to use and is more performant then reflection. You *COULD* implement your ICloneable to copy the object with reflection, but thats just plain silly.
I highly suggest you run some performance benchmarks on reflection and see just how slow it is.
Collin Jasnoch wrote: So were you planning on binding some UI elements to private properties??? Or
'Complex' properties as you put it? If so, the logic is already there... Because
you already implimented it. Also, if you want it to support private fields you
can certainly impliment that (I did not because I had no need for it)
OK, adding support for private properties was just a minor nitpick and that is trivial... but yeah, I'm binding to a complex property right now as I type this. How is your code going to handle:
Dictionary<string, Dictionary<string, CMTInfo[]>>
?
Thats a valid "complex" type that I'm binding to a TreeView.
Collin Jasnoch wrote: Do you really think the OP requires this anywhere???
Yeah, cuz, NOBODY uses the data grid . Data grid used IEditableObject as one example of a popular control that uses it.
Collin Jasnoch wrote: On a last point, even if you provide a nice implimentation of IEditableObject
(that somehow does NOT use reflection), you are now forcing a base class on an
object for simple functionality (see post above.. what like 10 lines of
code).
Whats your point? Anything you bind to in the UI needs to implement INotifyPropertyChanged / INotifyCollectionChanged anyways. Whats another small interface?
Anyways, even if you want to use the code you posted above, thats fine, but I'd still wrap it in an IEditableObject interface so it can be used with controls.
My initial objection was not that you were using reflection (although it IS slow and you aren't caching ANY of the really slow reflection methods), it was that you weren't using IEditableObject.
|
|
|
|
|
If its inside the object itself, I would just do a prop by prop copy. Expression trees are 1000x faster then reflection for get/set, but the startup cost is more, so those are more useful when you are getting the same prop over and over and can cache the lambda.
|
|
|
|
|
Some times I feel programmers get a bit carried away with implementing code. Building a dragster to take a midnight stroll around town for instance is a bit overkill. The poster simply asked for a process that would work for his issue. It seems both of you have valid ways on how to approach this but one thing remains which method is simpler to comprehend. Giving an explanation to some one that is more complex than he requires, while sound in theory, may not be the right solution for his particular issue. I'm still a big fan of if it works to fix the problem use it. You don't regrow an entire leg to fix a small cut you slap a band-aid on it.
I know you can argue that implementing the wrong programming techniques can potentially lead to problems in the future, but you can run into issues even using the correct ones. Now I apologize for derailing this gentleman's thread but after reading this I became even more confused as to how to accomplish the original question. I can just imagine that he may be just as confused.
Sometimes it helps to remember that people post here because they don't have the answers, and we need to remember not everyone can comprehend at the same level.
|
|
|
|
|
As I indicated to the other poster, it is (potentially) important to implement STANDARD interfaces rather then employing band-aid fixes. Just like WPF relies on you implementing INotifyPropertyChanged, some aspects of it rely on you implementing IEditableObject. The discussion got derailed on how the internals should work rather then the outside of the black box.
|
|
|
|
|
Thank you all guys, only now did I get the time to read all posts. To summarize what I learned:
1) .NET ships with IEditableObject interface which I am advised to implement in such situations
2) the implementation may use reflection, expression trees (not sure I quite understand this), or can be manually typed out for a particular class
3) the implementation (in any case) does nothing other that store a copy of the data for possible rollback later
4) .NET framework itself provides no extra advantage of using IEditableObject (except data grid and maybe few other specific controls) - a typical window with textboxes and checkboxes for data is unaware of IEditableObject and I must manually call BeginEdit, CancelEdit etc.
Therefore - if I just make the copy but not as an implementation of IEditableObject, it'll work the same, but it is not advisable because it is not standard practice.
Let me please know if I understand this correctly.
H.
|
|
|
|
|
Basically, that's spot on. Although it also ships with IEditableCollectionView which you may want to take advantage off if you are adding to collections.
|
|
|
|
|
That is kind of disappointing. Because really - the easy solution would be this: bind data model->controls only once. Do not bind back until said so (ie - user clicks OK). Maybe this would stand in the way of other things like validation, I don't know, but still I would expect that .net framework comes a bit more prepared for this very common scenario other than provide an interface any kid could write and let programmers worry about the rest.
Anyway, thanks for helping me understand this.
|
|
|
|
|
Did you download and try the sample in my blog entry? Basically I created a couple of reusable classes in there that you can just use in your project without needing to reinvent any wheels.
|
|
|
|
|
I got to give you 5 as this is exactly the approach I used (before I ran across IEditable). I copy the object in the selected property change and bind the editable## to the UI. Chucked the copy method in the ViewModelBase and never even think about it again!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I'm going to put my head on the block here and say that reflection works fine because while it's not the fastest solution, this tends not to matter to the user because this is not an operation they are going to be performing 1000s of times a second. That's why my solution uses reflection - it's easy to implement, easy to understand and conforms to the interfaces that WPF expects to see.
|
|
|
|
|
With silverlight4, how can i call the client program in web application? Only use Out-of-Brower, any other way?
|
|
|
|
|
What client application? Where is it running?
|
|
|
|
|
Dear Abby,
I have a bitmap that I am displaying on an Expander header.
<Image Source="{Binding TaskType, Converter={StaticResource ImageConverter}}" />
using the following ValueConverter
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
System.Drawing.Image img = global::ToDoManager.Properties.Resources.Pencil;
var bitmap = new System.Windows.Media.Imaging.BitmapImage();
bitmap.BeginInit();
MemoryStream stream = new MemoryStream();
img.Save(stream, ImageFormat.Bmp);
stream.Seek(0, SeekOrigin.Begin);
bitmap.StreamSource = stream;
bitmap.EndInit();
stream.Dispose();
return bitmap;
}
which is working except that the transparent area is black. I guess I need something, encoder maybe to preserve
the transparency. It's like when I'm creating the new BitmapImage it creates it without an Alpha channel.
I've googled but everything I've found leads to this solution and people admit there's a problem but no one
has offered a solution.
Jangled in Jacksonville
C'est What?
|
|
|
|
|
|
Not really, as that's not for a WPF Bitmap.
|
|
|
|
|
Good point well put - didn't notice that!
This one[^] talks about using GDI+ in combination with WFP to get alpha channels
C# has already designed away most of the tedium of C++.
|
|
|
|
|
Funnily enough, I've just posted a variant of that.
|
|
|
|
|
NO the link was no help because the converter converts from a Bitmap to a BitmapImage.
The reason you have to convert is that WPF uses the Bitmap image to take advantage of
the underlying DirectX.
But hanks for the effort.
Sects Therapy
|
|
|
|
|
If you're happy to use GDI+ as an intermediate step, you can get round this with something like:
public static BitmapSource MakeTransparent(this MemoryStream stream)
{
Bitmap bitmap = new Bitmap(stream);
bitmap.MakeTransparent();
return Imaging.CreateBitmapSourceFromHBitmap(
bitmap.GetHBitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);
}
|
|
|
|
|
I saw that solution in a couple of places but was hoping not to get my hands to dirty.
Also I'm afraid of performance issues as I'm trying to put an image in a DataGridView column where the application
is an VS2010 extension here[^] that I'm trying to add functionality. It's not a gotta have but thought it might enhance the
touchy-feely.
Thanks I'll give a shot and see how it works.
[update]
Worked like a charm but there was a gotcha;
1) Had to put it inline because I'm using in a ValueConverter it complained about it not being static then
when I made static it complained something about class needed to be non-generic???
var bitmap = new System.Windows.Media.Imaging.BitmapImage();
MemoryStream stream = new MemoryStream();
img.Save(stream, ImageFormat.Bmp);
stream.Seek(0, SeekOrigin.Begin);
bitmap.StreamSource = stream;
Bitmap bitmap1 = new Bitmap(stream);
bitmap1.MakeTransparent();
return Imaging.CreateBitmapSourceFromHBitmap(
bitmap1.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);
Thanks for the tip.
Sects Therapy
modified on Monday, September 5, 2011 4:27 PM
|
|
|
|
|
Great job there. Glad you have it working.
|
|
|
|
|
hello,
I am new to WPF, and i have the task to navigate between xaml files. the scenario is:
I use an external IDE "Aurora" from mobiform, which has loose xaml files, i want to implement hyperlink to move between different files via xaml
Thanks In Advance
ali
|
|
|
|