|
1. Depends on what kind of program you're writing
2. See #1
3. See #1
4. See #1
5. See #1
6. See #1
Your choices of tools and design methodologies should always depend on what you're trying to accomplish. The team developing Diablo 3 isn't going to use WPF and MEF, and a group developing an internal accounting system isn't going to be writing DirectX code... Different tools for different tasks.
|
|
|
|
|
Thanks Ian Shlasko,
Application is very simple stock management and accounting system ,
But problem is i am little but new in WPF + MVVM + Prism, so want to some guideline from u about this.
Any Link any think that help me.
|
|
|
|
|
Try this[^] out.
Too much of heaven can bring you underground
Heaven can always turn around
Too much of heaven, our life is all hell bound
Heaven, the kill that makes no sound
|
|
|
|
|
Given your questions I would suggest this is a very bad choice. Use the tools and languages that you understand and are comfortable with. Writing a major application in a language that you are new to is a recipe for disaster at worst, and severe pain at best.
If you just want to learn WPF then there are lots of beginner articles here on CodeProject; here[^] is a really good starting point.
The best things in life are not things.
|
|
|
|
|
Scrolling in nested Listbox
Hi Friends
Hope you all are doing good.
I have few questions about WPF List BOX
Some Background:
We are trying to build a scheduling control like outlook with some custom functionality.
I have already gone through the similar post in Code Project but we tend to take slightly different approach (trying to use MVVM approach).
Problem:
Currently we have a Listbox with 3 items. Each item in the list box is another Listbox with borders as sub items. For E.g. the XAML code looks like this.
<Grid Height="500" Width="500">
<ListBox Name="MasterListBox" HorizontalAlignment="Stretch">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBoxItem >
<ListBox Name="Child1" Height="240">
<ListBoxItem >
<Border Width="200" Background="Red" Height="40"></Border>
</ListBoxItem>
<ListBoxItem >
<Border Width="200" Background="Blue" Height="40"></Border>
</ListBoxItem>
<ListBoxItem >
<Border Width="200" Background="Green" Height="40"></Border>
</ListBoxItem>
</ListBox>
</ListBoxItem>
<ListBoxItem >
<ListBox Name="Child2" Height="240">
<ListBoxItem >
<Border Width="200" Background="Yellow" Height="40"></Border>
</ListBoxItem>
<ListBoxItem >
<Border Width="200" Background="Green" Height="40"></Border>
</ListBoxItem>
<ListBoxItem >
<Border Width="200" Background="Pink" Height="40"></Border>
</ListBoxItem>
</ListBox>
</ListBoxItem>
<ListBoxItem >
<ListBox Name="Child3" Height="240">
<ListBoxItem >
<Border Width="200" Background="Aqua" Height="40"></Border>
</ListBoxItem>
<ListBoxItem >
<Border Width="200" Background="Beige" Height="40"></Border>
</ListBoxItem>
<ListBoxItem >
<Border Width="200" Background="Brown" Height="40"></Border>
</ListBoxItem>
</ListBox>
</ListBoxItem>
</ListBox>
</Grid>
The problem is when I click on the 1st item(Child1) of the MasterListBox in the white area and drag right, the MasterListBox list box scroll to right, But when I click on the subitem (for e.g. say red border) and drag right the MasterListBox doesn’t scroll right.
I am aware that I am trying to drag the item of the inner list box and that’s the reason the outer list box is not scrolling, But it there a way we can override this. I want to select the inner item also so cannot set IsHitTestVisible="False" for inner item.
Thanks you for looking into this. Your help is greatly appreciated.
Regards
Saurabh
modified on Friday, July 22, 2011 7:37 AM
|
|
|
|
|
I would replace the inner listbox with an ItemsControl.
Don't be overcome by evil, but overcome evil with good
|
|
|
|
|
Hi all,
My application is just fine and could work like it is now.
It would be nice to have a kind of "Wait Window" with a progress bar (optional).
So I did the following, and the wait window is showing and closing when I want it:
wndSave oWindow = null;
void oOrg_Save(object sender, SaveEventArgs e)
{
this.isEnabled = false;
this.Dispatcher.Invoke(new DispatcherOperationCallBack((param)=>
{
oWindow = new wndSave();
...
System.Threading.Thread oThread = new Thread(updWindow);
oThread.Start();
wndSave.ShowDialog();
return null;
}), DispatcherPriority.BackGround, new object[] { null });
}
void updWindow()
{
oWindow.Dispatcher.Invoke(new DispatcherOperationCallBack((param)=>
{
foreach(myModel oModel in myView.Models)
{
System.Threading.ParameterizedThreadStart oStart = new ParameterizedThreadStart(mySave);
System.Threading.Thread oNewThread = new Thread(oStart);
oNewThread.Start(oModel);
Action showMethod = new delegate()
{
oWindow.UpdateProgress();
}
}
return null;
}), DispatcherPriority.BackGround, new object[] { null });
}
void mySave(object State)
{
myModel oModel = (MyModel)State;
myModel.Save();
}
If anybody has a trick how to refresh the progressbar would be nice. It is not necessary to be able to move the window, but it would be nice also. Don't know if it is a XBAP problem.
Thank you very much.
|
|
|
|
|
I just solved it by myself:
I had to remove the dispatcher and use an Action<t> instead. That did the job
|
|
|
|
|
Hi folks!
Is it possible to define the targettype of a style to be an interface or an abstract class.
Something like this (in pseudo code)
Style s = new Style();
s.TargetType = class where inherit from baseclass
or
Style s = new Style();
s.TargetType = class which implements given interface
This is needed for creating a generic dragdrop element, where the items in the source can be derived classes.
e.g:
abstract class DDItem<T,Q>
{
public T Identifier {get;set;}
public Q DisplayableContent {get;set;}
}
<ListBox>
<ListBox.Ressources>
<Style TargetType={x:Type local:DDItem}>
<EventSetter Event="MouseLeftButtonDown" Handler="Drag"/>
</Style>
</ListBox.Ressources>
</ListBox>
Would be fine to do this in plain c# as well.
Help would be appreciated!
|
|
|
|
|
Why don't you try inheriting the Style itself?
Silverlight 5 Tutorials : 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
|
|
|
|
|
Hello,
There's a lot of talk on the net about the View-ViewModel interaction but little about the ViewModel-Model interaction.
I have a Report that has (as a composition) a collection of Parameters. So I have a ReportViewModel that has a collection of ParameterViewModels, a ReportView bound to the ReportViewModel, and the ReportView in turn carries an ItemsControl-full of UserControls bound to the ParameterViewModels. The ReportViewModel's constructor gets passed the Report object and passes the Parameter objects in turn to the sub-viewmodels.
The Views and ViewModels interact nicely, the ViewModels "load" themselves from the underlying Models. More precisely, they keep a reference to the Model and synthesize whatever information the View needs.
Now for what puzzles me: when/how does the data flow back from ViewModel to Model ? When/how does the user's gesturing finally impacts the Model ?
I see that there are at least two possibilities...
1/ Live-update the Model whenever the ViewModel changes. Whenever we want to run operations on the updated Report, there's nothing extra to do.
2/ Implement an explicit "Apply" method in both ViewModels - obviosuly ReportViewModel.Apply will call ParameterViewModel.Apply. Whenever we need an up-to-date Report, first call Apply then save it somewhere, or print it, whatever.
What's your take on this ?
Jean-Louis
modified on Tuesday, July 19, 2011 7:49 AM
|
|
|
|
|
You're right. Too often the interaction from the VM back to the M is glossed over. The answer really depends on what you're trying to achieve though. If you are saving data from the view back to a database, for instance, you may want to batch all the changes from a particular edit and submit them at once. Alternatively, your backing store may be updated whenever a property passes validation. This is so dependent on your requirements that there are very few hard and fast rules.
|
|
|
|
|
When you are setting your binding to two-way, you are updating the model.
Yes, your view is bound to the viewmodel and not the model, but the view-model, but if your binding is two-way, the model is going to be udpated.
Maybe I've understood your question wrong here though.
Too much of heaven can bring you underground
Heaven can always turn around
Too much of heaven, our life is all hell bound
Heaven, the kill that makes no sound
|
|
|
|
|
I don't bind the view directly to model properties, and I don't want to change that. For starters, I don't like it. Moreover, in the general case it is not always possible. The ViewModel may contain properties that have no direct counterpart in the Model. Also my Model objects contain collections. So I would need to use ObservableCollections...but they're pulled from a Hibernate session so I don't even have control over the exact type of the collections.
|
|
|
|
|
I may have misread your post, but it seems to me like you have a fundamental misunderstanding of the ViewModel and Model portions. Yes, your View should only bind to stuff in the ViewModel only. However, the ViewModel is not creating, copying, storing, loading, saving, etc. the data, that is the models job. The ViewModel is simply a thin *wrapper* around the model and has a reference to it. If your model is implemented correctly, you shouldn't need much (if any) repackaging of the data. Your ViewModel generally just exposes a bunch of RelayCommands that manipulate the model. If you are doing a lot of repacking work in the ViewModel, or are copying around data a lot... as they say on teh internetz: "UR DOIN IT WRONG!"
|
|
|
|
|
Hmm, I don't think I have a "fundamental misunderstanding". In my app the ViewModel does not store or load data by itself - it tells a DAO to do so. As for validation, it asks the Model to do it.
Ok, let's imagine that we rewrite Notepad the MVVM way. We have a Document object with a string property - say Content. And a DocumentViewModel that holds a reference to a Document. It has a a string Content property too, which is loaded from the underlying Document. And then a DocumentView with a text box that binds to the DocumentViewModel's Content. I know I could bind to Document.Content directly but I've beaten that horse in my original post already.
Am I on the right track here ?
Now loading the ViewModel from the Model has been dealt with but what about the data flowing back from Mr/Ms User to the View to the ViewModel to the Model ?
My current take is this…
ViewModel exposes commands such as NewCommand, OpenCommand, SaveCommand, SaveAsCommand - and then some more like Copy/Cut/Paste Commands.
NewCommand.Execute checks whether pending changes exist and possibly offers to save. Then it sets the VM's Document to a "new Document()". The VM updates its Content property and fires an event.
SaveCommand.CanExecute returns True if the document has been changed. SaveCommand.Execute copies the text from VM.Content to Document.Content then tells some object to save the document - via an interface so it can be mocked and unit-tested.
SaveAsCommand.Execute…hmmm…I guess it sets the VM's Document to a "new Document()" before transferring the VM.Content to Document.Content. But this assumes that the VM has copied all the Document's information. Or maybe the Document is cloneable and we replace the VM.Document with VM.Document.Clone() ?
Now in my real app, it's a bit messier because the Document is a composition of other objects that have their VM too.
|
|
|
|
|
Jean-Louis Leroy wrote:
Ok, let's imagine that we rewrite Notepad the MVVM way. We have a Document object with a string property - say Content. And a DocumentViewModel that holds a reference to a Document. It has a a string Content property too, which is loaded from the underlying Document. And then a DocumentView with a text box that binds to the DocumentViewModel's Content. I know I could bind to Document.Content directly but I've beaten that horse in my original post already.
Am I on the right track here ?
---
No, that is exactly what you do *NOT* do.
In your example, you have DocumentViewModel that holds a reference to a Document(Model). Document(Model) has a string Content property (the content of the text file).
So far, so good.
The next step is where you head off the reservation a bit .
DocumentViewModel should DEFINITELY NOT have its own string Content property. It should simply *wrap* the one from the Document(Model). I.e.
DocumentViewModel.cs:
public string Content
{
get
{
return _document.Content;
}
set
{
if (_document.Content != value)
{
_document.Content = value;
OnPropertyChanged("Content");
}
}
}
The reasons for this are two-fold:
1) you don't have to worry about keeping the VM and M in sync, since they are always by design in sync
2) you are not storing the same data in multiple places. Imagine if the text file is 100 bytes... no biggie right? your design uses up 200 bytes of memory. No biggie. Now imagine if the text file is 1MB or 10MB or 100MB... with your design, you are using up 2MB, 20MB or 200MB of memory. Not good.
Rule #1 in good software design, ESPECIALLY in WPF & MVVM... is that you should only have one instance of an object in memory at all times. The reason why its more important in WPF is that imagine this scenario:
SomeObject (inst 1) ... somebody binds to it ... all good... anytime SomeObject (inst 1) is modified, the UI is updated
Now imagine that somebody went and made a COPY of SomeObject and now you have SomeObject (inst 2)... changes made to one will not update the properties in the other and data binding will be broken .
|
|
|
|
|
(quotes no in the same order as in the original text)
SledgeHammer01 wrote: DocumentViewModel should DEFINITELY NOT have its own string Content property. It should simply *wrap* the one from the Document(Model).
Here I stumble upon a difficulty. Consider a Person that has a birth date stored in a DateTime. Obviously we don't want to present that in the VM. Instead we want to map the double Person.BirthDate to a text input field in the view - or three text boxes for day, month and year, or some Calendar control. So what's the VM between View and Model going to look like ? Does it contain one (or three) string properties ?
Hmm, maybe something like this ?
public string Day
{
get { return _person.BirthDate.Day.ToString(); }
set { d = _person.BirthDate.AddDays(int.Parse(value)).AddDays(-_person.BirthDate.Day); }
}
public string Month
{
get { return _person.BirthDate.Month.ToString(); }
set { d = _person.BirthDate.AddMonths(int.Parse(value)).AddMonths(-_person.BirthDate.Month); }
}
public string Year
{
get { return _person.BirthDate.Year.ToString(); }
set { d = _person.BirthDate.AddMonths(int.Parse(value)).AddMonths(-_person.BirthDate.Year); }
}
Or maybe a ValueConverter is used somewhere ? I haven't explored that yet...
SledgeHammer01 wrote: Rule #1 in good software design, ESPECIALLY in WPF & MVVM... is that you should only have one instance of an object in memory at all times
I do see your point with having only one instance of an object in memory at all times...especially since I have implemented object-relational mappers like Perl's Tangram. If I have two views looking at the same Model at the same time, I'd want the changes made via one view to be reflected in the other view. Right ? And binding to the Model's property instead of copying them gives me just that.
Or does it ? Back to my Person.BirthDate example, suppose that I have VM1 that exposes the birth date as a single string property (BirthDate) in yyyy/mm/dd format. When the View sets the VM's BirthDate property the Model.BirthDate is updated. Now VM2 uses three string properties: Day, Month and Year. But changing the birth date via VM1 fires a "BirthDate" event that is significant only to the View that displays VM1. The change notifications are sent as changes to the VM's properties, whereas (if memory serves) in Smalltalk MVC they are sent as updates to the Model's properties.
There is also another possibility: bind the two views to the same ViewModel. This leads to another difficulty: what if the two views are so different that we'd normally use two different ViewModel classes ? We'd be forced to artifically merge them into some sort of Janus VM with four properties: Day, Month, Year, BirthDate.
Back to my real situation...I have a User which contains a collection of Reports. All that is persisted to a DB via NHibernate via a DAO. I want to support the New/Open/Save/SaveAs cycle for Reports. It means that "opening" a report means picking one from the collection in the User object. In the scheme you propose, Save would simply tell the DAO to update the object - no need to copy stuff from VM to M. But how do I implement SaveAs ? By the time I know the end user wants to make a new object, the old one has already been messed up.
edit: grammar
|
|
|
|
|
Jean-Louis Leroy wrote: I want to support the New/Open/Save/SaveAs cycle for Reports [...] But how do I implement SaveAs ? By the time I know the end user wants to make a new object, the old one has already been messed up.
Thinking about it, one solution out of this problem is to drop the SaveAs command (posterior to changes) and replace it with a Duplicate command (prior changes). Like in Mac OS X Lion
Then what would Save mean ? Worse, what would it mean if a user changes the data, then never executes Save ?
It seems to me that MVVM may end up curbing the way we design UIs. Another example, it discourages modal dialogs, or at least it makes them difficult to implement.
I wonder if it's legitimate for a code pattern to have such impact on the end-user experience. Isn't it the tail that wags the dog ?
edit: grammar
|
|
|
|
|
Jean-Louis Leroy wrote: it discourages modal dialogs, or at least it makes them difficult to
implement.
Why do you think it makes modal dialogs difficult to implement? I've never found that to be the case.
|
|
|
|
|
Pete O'Hanlon wrote: Why do you think it makes modal dialogs difficult to implement? I've never found that to be the case.
I suppose that many get their first exposure to MVVM via Josh Smith's article. But his sample app doesn't contain any modal dialogs. However, it's still one of the first things you need when implementing a real app. So when you turn to Google and search for "MVVM modal dialog" you get flooded with solutions falling roughly in five families: use a control; use a service; overlay a control on your view and disable its controls; what the heck, a bit of code-behind won't hurt; and finally, don't do modal, it's so nineties.
It seems that no consensus has emerged on the issue yet (or I've missed it). Not that I care that much about consensus anyway, but, by design or by accident, it's a difficulty for newbies...
What solution do you use ?
|
|
|
|
|
Over time, I've really settled into using one of two methods (primarily because I contributed to the solutions on them). I originally used the features of Onyx[^] to do the dialogs, but I then moved to using MefedMVVM[^].
I use a modal dialog service that I grab a hold of in my particular VM, and use that to instantiate the dialog. The trick is to use an interface to represent what you want from the dialog, and inject a concrete implementation of this at runtime. It's all very testable, and easy to support.
|
|
|
|
|
I don't see why people have problems with MVVM modal dialogs. There are many times when a modal dialog is perfectly appropriate. Yes, there are many, many different opinions on how they should be done. There is really only an issue if you plan to unit test your VM. The service solution usually works quite well and keeps the testability.
|
|
|
|
|
I agree the service approach is the way I do it, and I love it, works great.
Sacha Barber
- Microsoft Visual C# MVP 2008-2011
- Codeproject MVP 2008-2011
Open Source ProjectsCinch SL/WPF MVVM
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
My Blog : sachabarber.net
|
|
|
|
|
Jean-Louis Leroy wrote: Here I stumble upon a difficulty. Consider a Person that has a birth date stored
in a DateTime. Obviously we don't want to present that in the VM. Instead
we want to map the double Person.BirthDate to a text input field in
the view - or three text boxes for day, month and year, or some Calendar
control. So what's the VM between View and Model going to look like ? Does it
contain one (or three) string properties ?
If you have a date and/or time, I would use a date and/or time picker and keep the value as a DateTime. Having 3 (or more) text boxes throws out a ton of functionality that you would have for free and kind of makes your app look "low budget" IMO.
I do want to touch on something I said in my original response... IMO, the model should implement INPC so you CAN bind to properties in it directly. Imagine if you have 50 properties, it doesn't really make sense to wrap 50 properties just for the sake of wrapping them. Thats just a practice in typing. Unfortunately, thats not always possible. Web service proxies do not implement INPC, neither does native code, etc. There is absolutely nothing wrong with your VM exposing a Person property and your view binding to "Person.BirthDate".
Jean-Louis Leroy wrote: Or does it ? Back to my Person.BirthDate example, suppose that I
have VM1 that exposes the birth date as a single string property (BirthDate) in
yyyy/mm/dd format. When the View sets the VM's BirthDate property the
Model.BirthDate is updated. Now VM2 uses three string properties:
Day, Month and Year. But changing the birth date via VM1 fires a "BirthDate"
event that is significant only to the View that displays VM1. The change
notifications are sent as changes to the VM's properties, whereas (if
memory serves) in Smalltalk MVC they are sent as updates to the Model's
properties.
A properly implemented model should handle this case. Updating Day, month, year should send an INPC for Day (or month or year) AND Date. Updating the Date property should send an INPC for day, month, year and Date.
|
|
|
|
|