|
Hello Everyone
I have created a Client/Server application on C# on WPF IDE and I have a little problem on my UserClient property class...
Within this class I have a method called:
public override bool Equals(object obj)
{
UserClient temp = obj as UserClient;
if (temp != null)
{
return (userId == temp.userId);
}
if (temp != null)
{
return (userPass == temp.userPass);
}
return false;
}
The problem I'm having is:
The class UserClient is highlighted with a green line under-neath where when I place MouseOver it sas:
UserClient overrides Object.Equals but does not override Object.GetHashCode
Here is the entire UserClient class code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
namespace DtposClient
{
public class UserClient
{
private string UserFullName;
private string UserAccessLevel;
private int UserId;
private int UserPassword;
public string fullName
{
get { return UserFullName; }
set { UserFullName = value; }
}
public string accLevel
{
get { return UserAccessLevel; }
set { UserAccessLevel = value; }
}
public int userId
{
get { return UserId; }
set { UserId = value; }
}
public int userPass
{
get { return UserPassword; }
set { UserPassword = value; }
}
public override bool Equals(object obj)
{
UserClient temp = obj as UserClient;
if (temp != null)
{
return (userId == temp.userId);
}
if (temp != null)
{
return (userPass == temp.userPass);
}
return false;
}
public UserClient(string fullNam, string aLevel, int usId, int pass)
{
fullName = fullNam;
accLevel = aLevel;
userId = usId;
userPass = pass;
}
}
}
Could someone please help me crack this problem....
thanks in advance
kind regards
lapeci
|
|
|
|
|
lapeci, forum guidelines state "do not post the same question in more than one forum." see answer to question in C# forum.
"You get that on the big jobs."
|
|
|
|
|
That's easy. Whenever you override Equals , you are required to override GetHashCode . All you need to do is add an override for this method.
The reason you need to do this is because you have changed the way equality works, so without a custom hashcode, you can end up with two different objects with the same hashcode - hence a problem with equality.
BTW, you should have posted this in the C# forum as it's a generic C# problem. The fact that the application is WPF is neither here nor there.
|
|
|
|
|
You can always use the new method to create a method of your own (breaking away from the inheritance hierarchy).
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
My latest tip/trick
|
|
|
|
|
public class TreeItem
{
public string HeaderTag { get; set; }
public List<TreeStatusItem> StatusItems { get; set; }
public List<TreeItem> items { get; set; }
public TreeItem()
{
StatusItems = new List<TreeStatusItem>();
}
}
public class TreeStatusItem
{
#region Properties
[DataMember]
public string StatusText { get; set; }
[DataMember]
public string StatusValue { get; set; }
}
Here a TreeItem has a HaderTag which displays as the Header for the treeview, the StatusItems contains items of a different type and the items have a List of the container class itself.
The sample data would be
-RegionName(object of TreeItem type)
--Oustanding(object of TreeStatusItem type)
--Live (object of TreeStatusItem type)
--Areas(object of TreeItem type)
----Oustanding(object of TreeStatusItem type)
----Live (object of TreeStatusItem type)
----SubAreas(object of TreeItem type)
......
...
I need to bind the data which is List<TreeItem> to a silverlight treeview. I can`t figure out how the hierarchical template should be !!!!
When you fail to plan, you are planning to fail.
|
|
|
|
|
I create a class ReportNode, it uses the NodeTag property to store the actual record that is used to populate the treenode
public class ReportNode : ViewModelBase
{
public ReportNode(string sLabel, object oObject, string sColor)
{
NodeLabel = sLabel;
NodeTag = oObject;
Color = sColor;
}
public string NodeLabel { get; set; }
public object NodeTag { get; set; }
public string Color { get; set; }
private ObservableCollection<ReportNode> _ChildNodes;
public ObservableCollection<ReportNode> ChildNodes
{
get
{ return _ChildNodes; }
set
{
_ChildNodes = value;
base.OnPropertyChanged("ChildNodes");
}
}
}
Hierarchical data template binds the itemssource to the ChildNodes collection.
When loading the nodes I stuff the NodeLabel with the text to display and the list object goes in the NodeTag property. When accessing the node I test the typeof the nodetag to determine what to do with the node. I have 1 tree with 6 different data sources, works perfectly.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Incorrect post.
Sorry
modified on Friday, February 4, 2011 5:51 AM
|
|
|
|
|
Stop posting multiple versions of the same question. You could follow this through in one thread, so that is what you should do. Honestly, you've asked more than enough questions on the forums to know this - and, btw, you should try to avoid the code behind; read about MVVM.
|
|
|
|
|
My database table contains two fields, id and name
What is the way to populate the combobox with the projectnames and have the id of each projectname assigned aswell.
This is required so that if for example, from a list of names in a listbox, a name is selected, then I want the projectname to be selected in the project combobox.
The table returns the name and the projectID
I can populate the combobox with the projectnames from the project table but not sure how to assign the IDs to them.
<ComboBox Name="cboProjects" SelectedIndex="{Binding Path=ProjectID}"
/>
Thanks
|
|
|
|
|
You need to bind to DisplayMemberPath and SelectedValuePath I think.
In your example you're not showing how you're populating the combo at all, so not exactly sure if this is what you are after...
If you have a List<items> collection to which you bind, then each Item has an Id and Description - you bind the DisplayMemberPath to Description and the SelectedValuePath to Id
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
I have now included the real sample of what I am trying to do...
You see that first I am retrieving data from a stored procedure which then correctly gets populated into a listcollection called grades.
First problem is that the combo box does not get populated.
Note that I can see there is correct data in cboGrades.ItemsSource
Do you see what I am doing wrong please?
Thanks
public static List<clsStudentDetails> GetGrades()
{
DbCommand comm = clsGenericDataAccess.CreateCommand();
comm.CommandText = "uspGetGrades";
DataTable table = new DataTable();
table = clsGenericDataAccess.ExecuteSelectCommand(comm);
List<clsStudentDetails> grades = new List<clsStudentDetails>();
for (int i = 0; i < table.Rows.Count; i++)
{
clsStudentDetails details = new clsStudentDetails();
details.GradeID = int.Parse(table.Rows[i]["GradeID"].ToString());
details.GradeName = table.Rows[i]["GradeName"].ToString();
grades.Add(details);
}
return grades;
}
---------------------
private void PopulateGrades()
{
List<clsStudentDetails> studentDetails = new List<clsStudentDetails>();
cboGrades.ItemsSource = clsStudentAccess.GetGrades();
}
---------------------
<ComboBox Name="cboGrades" DisplayMemberPath="GradeName"
SelectedValuePath="GradeID"
Width="208" />
|
|
|
|
|
A quick squiz shows nothing obviously wrong...
in PopulateGrades I would change so that it reads
studentDetails = clsStudentAccess.GetGrades();
cboGrades.ItemSource = studentDetails;
and check in debug that the studentDetails collection really does contain the data you think it does.
I usually start with some dummy data too - just to make things snappier..
private List<StudentDetails> GetDetails()
{
List<StudentDetails> studentDetails = new List<StudentDetails>();
studentDetails.Add(new StudentDetails()
{
GradeId = "1",
GradeName = "Top Grade"
});
studentDetails.Add(new StudentDetails()
{
GradeId = "2",
GradeName = "Not too bad"
});
studentDetails.Add(new StudentDetails()
{
GradeId = "3",
GradeName = "Try Harder"
});
return studentDetails;
}
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
So, I have everything completed with no code in the code behind. I have everything separated. How should my view model notify the view that the database update has worked? Any thoughts or examples on how to do this?
I didn't get any requirements for the signature
|
|
|
|
|
You could simply add a dirty flag and bind to this.
|
|
|
|
|
Your VM needs to expose some property that indicates success or failure.
You might need a converter because there are three or four states you're talking about:
1. Don't have a pending update
2. Have a pending update
3. Update failed
4. Update passed
(2. is only appropriate for asynchronous updates)
So your VM has a property that starts off with a value 1.
When the 'save' command is triggered, it is set to 2.
When the results of the Save are returned t is set to 3 or 4 respectively.
You could 'merge' this with any process you are using to enable/disable the Save button - so add another state ...
0. Nothing To Save
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
Bind the status to a textblock and create a property for it in your view model (assuming everything is bound to the view model).
Once your async web service comese back from the server, fire an action to get to the view model and then let INotifyPropertyChanged take over to update the status.
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
My latest tip/trick
|
|
|
|
|
This is what I did. I guess the user will have to click a link to navigate, or I can put that in the code behind. Thanks for the reply.
I didn't get any requirements for the signature
|
|
|
|
|
Strange. You should not need to - are the datacontext's correct?
The funniest thing about this particular signature is that by the time you realise it doesn't say anything it's too late to stop reading it.
My latest tip/trick
|
|
|
|
|
We use the MVVMlight framework from Galasoft, it has a messaging construct. In the completed method we send the name of the method via a Completed message pump, the relevant view or viewmodel subscribes to the Completed message, checks the message content and takes action as appropriate.
We use a VERY simplified structure, I know it can get a lot more complex but this meets our current needs.
However I rarely (never) use it to navigate as the datacontext generally meets our needs (data refreshes after the call and updates the UI via onpropertychanged)
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
I'm working on a WPF app that has to have rows of controls added at runtime. The rows will be fairly simple - Caption and TextBox, and in some cases, a button to the right.
Since I'm using MVVM, all the View has is:
<ScrollViewer VerticalScrollBarVisibility="Auto">
<StackPanel Name="pnlControls"/>
</ScrollViewer>
Now in the ViewModel when I pull the data that represents the rows, how do I add them to pnlControls?
Thaks
Everything makes sense in someone's mind
|
|
|
|
|
In the code where you read your rows, add something like this:
foreach (var row in myRows) {
var btn = new Button {Content=row.ButtonCaption};
btn.Click += NotifyButtonCallback;
pnlControls.Children.Add(btn);
var txt = new TextBox {Text=row.TextBoxText};
pnlControls.Children.Add(txt);
}
private void NotifyButtonCallback(object sender, RoutedEventArgs e) {
} You will need some additional "bookkeeping" to establish a connection between a UI element that you create dynamically and the row from which you created it, so that you could act upon user's actions, such as editing the text or clicking a button.
|
|
|
|
|
But the problem is that pnlControls is not accessable from within the ViewModel.
Everything makes sense in someone's mind
|
|
|
|
|
You should really handle this in the View not the ModelView. The ModelView should be independent of the View. MVVM light has a nice messenger pattern which you can use. Basically when the ModelView determines a new control needs to be added, it transmits a message which the View subscribes to. The View receives the message and then adds the control.
I'm not a huge fan of MVVM so others may argue the point but that's how I do it.
"You get that on the big jobs."
|
|
|
|
|
You need to bind to a collection in your viewmodel and use a DataTemplate to describe how the buttons are to be displayed.
If it wasn't for the fact that I'm in the middle of debugging MS Access programs, I'd probably be able to find an example!!
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|
|
Got bored with the MS Access - here's a real simple example...
The temnplate tells it how to display. THe vm has an Options property containing a collection of Option - each of which has an OptionName property
<base:BaseView.Resources>
<DataTemplate x:Key="ButtonTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Button Content="{Binding OptionName}" Height="32"/>
</Grid>
</DataTemplate>
</base:BaseView.Resources>
<StackPanel Background="#FFFF00" Height="150">
<ItemsControl ItemsSource="{Binding Options}"
ItemTemplate="{StaticResource ButtonTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
Hope that's enough to get you started - you need to work out how you're going to handle clicks, of course... each button may bind to the same command with a varying parameter, or each to its own command - I haven't done this bit (back to the MS Access now!)
___________________________________________
.\\axxx
(That's an 'M')
|
|
|
|