|
Mark Salsbery wrote: Oh yes!
Let see, still I'm working on with user controls.
Mark Salsbery wrote: (fixed link in post above)
Thanks
I appreciate your help all the time...
CodingLover
|
|
|
|
|
Hi,
I am new to MVVM and trying to implement it in my application.
I have a develop a GUI which will interact with the Hardware through some protocol. This is first experience under this space.
Just to keep things simple, consider I have a hardware which contains Voltage and Resistance parameter at different sections of the hardware.
View
----
So, I have total 5 sections. Each of them contains 15 different Voltages and Resistance.
In my WPF GUI, I am representing these 5 sections in a tab control.
I have created a user control(PowerControl) that contains 2 sliders for Voltage and Resistance. Voltage varies from 0-120v and Resistance varies from 1-10 ohm.
Each of the sections in the tab control contains 15 user controls.
Model
-----
I am planning to create a class Power which has 2 properties for voltage and Resistance.
ViewModel
---------
I am planning to create a class 'PowerViewModel' to represent the Power model. It will have two properties which will have INotifyProperty changed event.
The change from the slider has to be conveyed to the hardware and it is done through a set of uniquely identified parameter.
Such as if a slider on the PowerControl of section 2(tab2) is moved, it 'll be represented as "PC2, section2, value of slider". So, its a combination of these three things and I used to send it the hardware which displays it in the hardware display.
Here are my questions.
1- Where should I write the unique ID's? Should it be in the Model or ViewModel?
2- How should we bind the slider as per their ID's?
3- How does my Model know which slider has been moved?
4- How can we apply MVVM here?
Thanks in advance and please feel free to ask for any clarification on this.
Praveen Raghuvanshi
Software Developer
|
|
|
|
|
I'll take a stab here...
If the IDs don't need to be in the model then they should be used in the viewmodel.
But, if you have separate objects in your view model - each associated with individual PowerViewModel objects, then you can bind those to each user control. Then you don't need IDs and the model knows what slider is moved.
Mark Salsbery
Microsoft MVP - Visual C++
modified on Tuesday, May 24, 2011 4:53 PM
|
|
|
|
|
Appreciate the quick response. I'll try it.
Praveen Raghuvanshi
Software Developer
|
|
|
|
|
For MVVM you're kinda doing it the wrong way around - you should create your VM first and then design a view. Anyhow, I know lots of people work better visually, so:
You have five sections each with a collection of 'Voltages and resistances'
So you want a SectionViewModel that contains a collection of VoltageAndResistanceViewModels - each of which has a Voltage property and a resistance property -which utilise INotifyPropertyChanged
Then you want another ViewModel that contains a collection of the SectionViewModel
I'd say that when you instantiate each of your ViewModels you'd need to tell them which unique Id for the hardware they are representing. This information (I would htink) would be contained in the model as a series fo collectins - so you would construct your collection of ViewModels based upon these collections, hence the Model has the unique Ids, which are referenced by the viewModels
Each slider would be bound in Xaml to the appropriate property of the particular VM to which the View is bound
When the property of the Vm is changed, if necessary that's the time to adjust the property on the model - the model can then do whatever it does in order to update the machine's value.
Hope that helps at least a little!
|
|
|
|
|
Appreciate the quick response. Very well explained. I'll try it
Praveen Raghuvanshi
Software Developer
|
|
|
|
|
I'm working on a WPF app using MWWV. I passed a data model into the CTOR of the viewmodel and set the bound properties from it.
In the view, is it possible somehow to set the width of a textbox based on the size of a field in the DB? How would you even know the width using MVVM?
Everything makes sense in someone's mind
|
|
|
|
|
Kevin Marois wrote: is it possible somehow to set the width of a textbox based on the size of a
field in the DB
Are you talking about setting the width of a textbox based on the size of the field, so if you had an NVARCHAR(50), you'd set the width for 50 characters? If you are, then your ViewModel would have a property which you'd set with this value multiplied by the width of the widest character in the font you are working with (this would normally be W in a Latin font).
In order to work out what the width of the font is, you have the choice of precalculating it and applying it as a constant, or you can use the following code:
FormattedText formattedText = new FormattedText("W", CultureInfo.GetCultureInfo("en-GB"), FlowDirection.LeftToRight, new Typeface(textBox.FontFamily.ToString()),
textBox.FontSize, Brushes.Black);
|
|
|
|
|
If the table has a name field whih is 50 characters, then I want the field on the form to be wde enough to accept 50 characters.
Everything makes sense in someone's mind
|
|
|
|
|
You are going to run into a problem with your idea... WPF UIs use TrueType fonts. For example, on my screen 10 W's are about 4x as wide as 10 i's. You'd have to size your field to fit W's since that is the widest character (in English -- USUALLY), so you'd end up with a bunch of empty space for most other characters since they are much narrower. You could switch to a fixed width font, but then it wouldn't match the rest of the UI and you'd lose various functionality / behavior from TrueType fonts.
If you still want to go down that route, Petes code snippet will allow you to calculate the width you need, then you'll need to add in some padding depending on the control.
|
|
|
|
|
Then if you follow my suggestion, you should be OK.
|
|
|
|
|
Do you need to set the width, or the maximum number of characters?
|
|
|
|
|
In this problem I have a screen displaying with the results of any operation a user performs.
It has an image control on it and the binding for source is as such:
<pre>
<Image Height="150" HorizontalAlignment="Left" Margin="94,12,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="179" Source="{Binding ElementName=isFailure, Path=IsChecked, Mode=OneWay, Converter={StaticResource ImageConverter}}" />
</pre>
The ElementName isFailure is a hidden checkbox on the form. The ViewModel sets the value to checked or unchecked for the application being in an error state. The design approach is that the image changes from thumbs up to thumbs down for a failure and one lable's text changes as well.
The text change works great. It flips back and forth easily.
The image change leaves me with a blank image window. If I manually change it either image displays fine. But programmatic change of Source fails. (Yes the class name does not match ImageConverter....ImageConverter is the name given to the ImageStateConverter in the controls Resources definition.) My ImageConverter is as follows:
<pre>
/// <summary>
/// Determines which image resource to use based on the state of a hidden checkbox on the form
/// </summary>
public class ImageStateConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (bool)value == true
? "/SIMS;component/Views/images/thumbs_down.png"
: "/SIMS;component/Views/image/thumbs_up.png";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
</pre>
Now I figure I have to call something on the control to force it to reload the image prior to doing a control.Show(); but I'm having trouble finding how to force it to reload the resource!
Suggestions?
Michael
|
|
|
|
|
1) Why are you getting / setting a hidden checkbox? Thats kind of hacky. Why not do it the right way with a DP or have your ViewModel implement INPC?
2) Image.Source is an ImageSource property. What you are returning is not an ImageSource. You are returning a string.
Try something like this instead:
return new BitmapImage(new Uri("pack://application:,,,/SIMS;component/Views/image/thumbs_up.png", UriKind.RelativeOrAbsolute));
Or whatever the correct path is.
|
|
|
|
|
Well,
First off I did not ask for comments on how I have a boolean passed to my binding.
Secondly the definition of the Source field is a path to the image. In this case the strings define the path to the resource within the current active assembly. Also as stated the one image worked. Turns out that the problem was in the path to the second image. Once I removed the s from images, the image loads just fine.
Finally now that both have been tested I can then do the refactoring for proper handling of the boolean.
|
|
|
|
|
Michael J. Eber wrote: First off I did not ask for comments on how I have a boolean passed to my binding.
So if someone you asked advice from spots a lousy design you don't want to hear about it. A comment like that above will not endear you to the very people you are looking to for advice. It would have been better to acknowledge the problem and thank him for pointing it out.
I thought it was an excellent answer, fixed your problem AND pointed out a lousy design issue.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
While I don't usually support "compensating"... thanks man... that was a really retarded 1 vote . I didn't really get his rudeness / ungratefulness considering we all do this for free... but whatever. I will certainly be putting "Michael J. Eber" in my "DO NOT HELP" list.
|
|
|
|
|
Excuse me sir, but if you read my response carefully you will see that his answer was wrong and did nothing to fix my problem.
He stated my problem was that I was feeding it a string. Per documentation the Source is specifically a URI of the location.
His 'fix' was copy and pasted from the poor example posted out on MSDN. It was a wrong answer because my solution now works and all I am doing is passing the path within the assembly of the image, which is what the documentation states for that field. If he was totally correct, and source only takes a BitMapImage then I'd greatly appreciate it.
Secondly, while I was a bit short on his comments of my hack it was a statement made with no concept of what I was doing. As it turns out this screen was a prototype and we pumped in a quick and dirty way to get a functional boolean into the form.
Finally, the form was not an application form tied to a ViewModel as he assumed. It was a dialog being used by a View Model that was facing a great deal of redesign once the changing images and text were functional. Was it not a good design? Quite possibly. But it had absolutely NOTHING to do with my question.
And now, like a little child, he is running around rating everything of mine as 1. So how is not endearing themselves to people?
|
|
|
|
|
Michael J. Eber wrote: you will see that his answer was wrong and did nothing to fix my problem.
Yes I noticed that after posting - sorry.
Michael J. Eber wrote: As it turns out this screen was a
prototype and we pumped in a quick and dirty way to get a functional boolean
into the form.
That would have been a better reply in the initial response, we all hack something up when developing. I'm glad you got the problem fixed - and published it so others can benefit.
And you are right univoting is childish (although your answer on file access was incorrect and was voted on content)!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I have a silverlight app where the user can download the image to whereever he wants. Works fine, but now I need to save a "world file" with the image. It should be the same file name in the same path, just a different extension. However, I am unable to change the "SafeFileName" or get the path and location of the previously saved image file. I would even be willing to open a second SaveFileDialog, but I can't initialize the name of the file - or force the path. Is there any hope here?
Thanks
Brent
|
|
|
|
|
Yup, you cannot change the SaveFileName property in the dialog.
You will have to parse the directory from that name, construct your own file name/extension, and save the file manually using System.IO.File.
|
|
|
|
|
Michael J. Eber wrote: and save the file manually using System.IO.File.
I didn't think that was possible in SL.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Michael J. Eber wrote: You will have to parse the directory from that name, construct your own file name/extension, and save the file manually using System.IO.File.
Not possible except maybe for out-of-browser apps with elevated trust...
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
The only real way to do this is to step outside Silverlight altogether, and use JavaScript to perform the downloads. There's a good explanation on how to do this here[^].
|
|
|
|
|
Thanks,
After further searching I also found code to put all the files into one zip file. I don't think it works on all platforms (Macs for example), though.
http://slsharpziplib.codeplex.com/[^]
Brent
|
|
|
|