Calling a method from a different ViewModel - c#

I'm writing a program for managing a tool inventory and have run into a problem when I have the users mark a tool as 'fixed'.
The program should work as follows:
Using TIView, TIViewModel, TIModel:
Employee checks tool out.
Tool happens to get damaged during use.
Employee return's the tool marking it as damaged and reporting the problem.
The tool is marked as returned and locked from being check out until fixed.
Using VPRView, VPRViewModel, and VPRModel:
An inspector goes into a data grid showing all tools with problems.
The inspector corrects the problem, marks the tool as fixed, then submits the data.
The program updates the SQLite database with the inspectors ID number, their solution, marks the problem as fixed and logs the date/time of completion.
THE PROBLEM STEP:
8. The program then runs the PopulateToolInventory method from the TIViewModel to update the inventory list so that the tool is no longer locked.
Summarized:
When the inspector marks the tool as fixed the database is updated using the VPRView, VPRViewModel, and VPRModel. The method to pull the data for the tool inventory is found in the TIViewModel. How do I get the application to execute the 'PopulateToolInventory' method from the VPRViewModel after uploading the data to the database via the VPRViewModel?
Code Sample:
VPRViewModel:
public void SubmitSolution()
{
VPRModel vprm = new VPRModel();
vprm.SubmitProblemSolution(ProblemSolved, ProblemSolution, InspectorID, SelectedReport[0].ToString());
ProblemReports = vprm.RetrieveProblemReports();
InspectorID = null;
ProblemSolution = null;
ProblemSolved = false;
MessageBox.Show("Solution successfully recorded!", "Success!", MessageBoxButton.OK);
// This is where I would want to call the method from the TIViewModel to update the data grid on the TIView.
}
TIViewModel:
private DataTable _toolInventory;
public DataTable ToolInventory
{
get { return _toolInventory; }
set
{
_toolInventory = value;
NotifyOfPropertyChange(() => ToolInventory);
}
}
public void PopulateToolInventory()
{
TIModel tim = new TIModel();
ToolInventory = tim.RetrieveToolInventory();
}
ShellViewModel:
class ShellViewModel : Conductor<object>
{
public void Open_ToolInventory()
{
ActivateItem(new TIViewModel());
}
public void ViewProblemReport()
{
WindowManager wm = new WindowManager();
VPRViewModel vprvm = new VPRViewModel();
wm.ShowDialog(vprvm);
}
}
FYI: I'm using Caliburn.Micro if this helps with any solution.
Hopefully this is enough information. If not, just ask for what you need! Also, please don't eat my code alive. I'm self taught and know that I'm far from a professional developer but this is a passion of mine and I'm really enjoying it. Constructive criticism is appreciated, just please don't make me feel stupid.

Using Ed's idea in the question comments I did the following.
class ShellViewModel : Conductor<object>
{
public void Open_ToolInventory()
{
ActivateItem(new TIViewModel());
}
public void ViewProblemReport()
{
WindowManager wm = new WindowManager();
VPRViewModel vprvm = new VPRViewModel();
wm.ShowDialog(vprvm);
}
}
Was changed to:
class ShellViewModel : Conductor<object>
{
TIViewModel tivm = new TIViewModel();
VPRViewModel vprvm = new VPRViewModel();
public void OpenToolInventory()
{
ActivateItem(tivm);
}
public void ViewProblemReport()
{
WindowManager wm = new WindowManager();
wm.ShowDialog(vprvm);
tivm.PopulateToolInventory();
}
}
This runs the targeted method after the dialog is closed updating the tool inventory to reflect all the solved problems at once. You're the best, Ed!

Related

Method, Delegate and Event Subscription Help in Autodesk Inventor Add-In

I'm creating an add-in for Autodesk Inventor. Basically, you define the buttons you want to add, and tell the app to add the button definitions. The problem I'm having is that when I define the 'OnExecute' method for the button definition, the button doesn't execute. I think the way I'm trying to organize the code is what's creating the problem.
I have a CustomButton class that has a delegate property that looks like this (the signature is void with an input of a NameValueMap Interface)
public class CustomButton
{
// … properties and methods that don't matter here
public ButtonDefinitionSink_OnExecuteEventHandler Execute { get; set; }
}
In the main Activate() method (what's called when Inventor starts) I create an instance of the following class to set all the button definitions and the methods that fire when they are clicked. That class looks like this:
public class CustomButtonDefinitions
{
public CustomButtonDefinitions(ref Application app)
{
_inventorApp = app;
InitializeButtonDefinitions();
}
public List<CustomButton> CustomButtons { get; set; } = new List<CustomButton>();
private void InitializeButtonDefinitions()
{
AddTestButton();
}
private void AddTestButton()
{
var testButton = new CustomButton
{
DisplayName = "test",
InternalName = "testCommand1",
Ribbon = "Assembly",
RibbonPanel = "Simplification",
IconSource = "./Assets/test.jpg",
Classification = CommandTypesEnum.kFileOperationsCmdType,
ShowText = true,
UseLargeIcon = true,
};
testButton.Execute = TestButton_Execute;
CustomButtons.Add(testButton);
}
private void TestButton_Execute(NameValueMap Context)
{
// This is where the logic of the button would go.
// For now, just something that gives me an indication it worked.
System.Windows.Forms.MessageBox.Show("Hello");
_inventorApp.ActiveDocument.Close();
}
}
Where I think the source of the error comes from is the next code (this is in the Activate():
CustomButtonDefinitions customButtonDefinitions = new CustomButtonDefinitions(ref _InventorApp);
foreach (var button in customButtonDefinitions.CustomButtons)
{
// this creates the button in Inventor
var buttonDef = button.CreateButtonDefinition(ref controlDefs);
// and this subscribes the button click event to my method
buttonDef.OnExecute += button.Execute;
}
There must be something un-subscribing my method from the button click event.
I'll be posting this in the Inventor forums as well, but wanted to check here too since I'm new to delegates and event handlers. I'm either not understanding something about delegates/events or it's something Inventor specific that I'll need some other help with.
Hopefully this is enough to give some context. Thanks in advance.
The problem was the fact that I wasn't creating the button definition in a high enough scope. I needed to create a variable above the scope of the Activate() method so the app could see it when needed.

GTK# sctructure of application

I am newbie in desktop application programs and I want to create an applications which will use only 1 window for all things. First of all I create a simple LOGIN form with "Login" button and 2 text fields. When user successfully logins window changes it's form. I pinned a picture of the, lets say, MAIN form, where user can switch between "screens" (I don't know how to properly name it) by clicking 1..4 buttons at the right. And we have the top panel with profile photo and nickname which persist all the time program still in the MAIN form.
So, the main question is: HOW should I do it? Which widgets I should use and how does dynamic content in GTK+ (and others, like Qt etc.) should be implemented? So I want answers, links to topics which covers this situation, guides and lessons. Anything will help.
I read a lot of documentation but it seems that I can't find proper information just because I don't know how to formulate my problem for search query.
Thank you, I hope I'll find some help.
P.S. I am gonna use C# and GTK# for this application.
You only need to create various boxes (Gtk.VBox or Gtk.HBox), and hide/show them as you need to. I did not know about Gtk.Stack, but I bet it uses the same principle, maybe with some optimization.
class UniqueWindowView: Gtk.Window
{
void Build()
{
var vbMainBox = new Gtk.VBox();
this.vbLoginPage = this.BuildLoginPage();
this.vbNotebook = this.BuildNotebook();
vbMainBox.PackStart( this.vbLoginPage, true, true, 100 );
vbMainBox.PackStart( this.vbNotebook, true, true, 5 );
vbMainBox.Show();
this.Add( vbMainBox );
this.SetSizeRequest( 600, 400 );
this.Show();
}
// ...
public Gtk.VBox vbLoginPage {
get; private set;
}
public Gtk.VBox vbNotebook {
get; private set;
}
public Gtk.Notebook nbNotebook {
get; private set;
}
public Gtk.Button btLogin {
get; private set;
}
}
Once you have this scheme running, you have to prepare to show or hide the appropriate boxes.
class UniqueWindowCtrl
{
public UniqueWindowCtrl()
{
this.view = new UniqueWindowView();
this.view.DeleteEvent += (o, args) => this.Quit();
this.view.btLogin.Clicked += (sender, e) => this.ShowNotebook();
}
public void Start()
{
this.ShowLogin();
}
public void ShowLogin()
{
this.view.vbLoginPage.Show();
this.view.nbNotebook.Hide();
}
public void ShowNotebook()
{
this.view.vbLoginPage.Hide();
this.view.nbNotebook.Show();
}
void Quit()
{
this.view.Hide();
Gtk.Application.Quit();
}
UniqueWindowView view;
}
You can find the whole source code for a unique window in GTK# here.
Hope this helps.
I suggest you take a look at GtkStack. This will enable you to have multiple widget layouts in a single window and provides you with an easy way to change which widgets are shown. GtkStack is commonly used with StackSwitcher. However normal buttons will work just as well. Can I also suggest you use Glade to lay out your widgets? This will give you a presentation of how your widgets sets will look.
Edit: GtkStack does not appear to be available for Gtk#.

Datagrid not refreshing

Hi I have a datagrid that is populated via an ICollectionView
public ICollectionView MemberView { get; private set; }
Members = new ObservableCollection<Member>(_memberService.LoadCustomers());
MemberView = CollectionViewSource.GetDefaultView(Members);
All works fine until I update a status on a member to 'Live' from another viewmodel.
I then try and search on this recordset but the record never turns up until I restart the application.
I am using MVVMLight and the messenger to trigger the reload (Not really important here as the messagebox confirms its running correctly)
private void NotificationMessageReceived(NotificationMessage msg)
{
if (msg.Notification == "ReloadClients")
{
Members = _memberService.LoadCustomers();
MemberView.Refresh();
RunFilter();
MessageBox.Show("Clients Reloaded");
}
}
Am I going about this the correct way? Any help will be very much appreciated.
Thanks Scott

Strange DB-context behaviour when updating collection (Works when stepping through the code in debugger)

I have a really strange behavior that actually gives me different result if I step through the code using the debugger or just run the app (press play).
The model looks like this;
public class QuestionPack
{
public int QuestionPackID { get; set; }
public string Hashcode { get; set; }
public virtual ICollection<Question> Questions { get; set; }
}
And I save this class to the DB using a repository-pattern like this;
public class EFQuestionPackRepository : IQuestionPackRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<QuestionPack> QuestionsPacks
{
get { return context.QuestionPacks; }
}
public void SaveQuestionPack(QuestionPack questionpack)
{
if (questionpack.QuestionPackID == 0)
{
context.QuestionPacks.Add(questionpack);
}
else
{
QuestionPack dbEntry = context.QuestionPacks.Find(questionpack.QuestionPackID);
if (dbEntry != null)
{
dbEntry.Hashcode = questionpack.Hashcode;
dbEntry.Questions = questionpack.Questions;
}
}
context.SaveChanges();
}
}
This works perfectly when adding data, but when I try to update (the else statement) I get doubles on the Questions, eg. the questions get saved but with the already saved questions so if i have 4 questions, update that question with ONE question and save, i will end up with 9 questions.
BUT; if I step through the code using the debugger (start from the SaveQuestionPack-function and hit "continue", after context.saveChanges()" I get the expected result. I’m so confused I don’t even know where to start looking.
I guess it have something to do with the fact that I’m trying to store a collection, but why does it work when I step through the save process?
Any input is appreciated.
I think i solved it but im not really sure why it works...
I added this;
dbEntry.Questions.Clear();
before;
dbEntry.Questions = questionpack.Questions;
Anyone having a idea why this corrected the fault?

Save data to SQL DB using a class in C#

Sorry If I am posting this question in the wrong forum. This is my first time posting at Stackoverflow. And Also I am learning ASP.NET and C# by myself so pardon me if this elementary.
I have created a class file in ASP.NET 4.0 C# using visual studio 2010. My code is like below
namespace My.Customers
{
public class EmailMailingList
{
#region members
private string _emailList;
#endregion
#region properties
/// <summary>
/// gets or sets Customer Email for Mailing List
/// </summary>
public string EmailList
{
get { return _emailList; }
set { _emailList = value; }
}
#endregion
}
}
I have a Database table in SQL 2008 named MailingList with 2 fields namely Id and Email where Id is int with auto increment and Email Varchar(50).
I also created a Stored Procedure based on this table to enter the email address.
where I am getting confused is How can I add this info to my class file so the data can be saved to the database.
I also created a web form called Join-Mailing-List.aspx with a textbox called tbEmail and a Submit Button called Join.
What I am trying to is when someone enters the email address in the textbox I want to pass the textbox value to string EmailList in my class file and save the data to the database.
I know how to pass the textbox value to my class file. I just dont know how to save the info to the DB without using the DB code in the aspx page
Thanks and really appreciate for any advice or examples
There are a number of different ways to save information to a database using C#. Some of the more common:
ADO.NET
Linq-To-SQL
Entity Framework
You will probably need to read up on those to find the best one for you. If you want something quick and relatively easy, I would probably go with ADO.NET but others may disagree.
As far as how to include the code for the update in your class you could just add an Update() or Save() function.
There are several ways you can approach saving into database
Here is one: (simpler in my opinion)
public class EmailMailingList
{
private string _emailList;
public string EmailList
{
get { return _emailList; }
set { _emailList = value; }
}
#endregion
public void Save()
{
//Insert (this.EmailList); to database
}
}
//Use:
EmailMailingList ml = new EmailMailingList();
ml.EmailList = "blah";
ml.Save();
Some school of thought frown at that.
Another is creating a special class to do that
public class MailingListSaver
{
public static void Save(EmailMailingList ml)
{
//insert (ml.EmailList) into database
}
}
//Use:
EmailMailingList ml = new EmailMailingList();
ml.EmailList = "blah";
MailingListSaver.Save(ml);
Look into (google)
Active Record Pattern
Repository Pattern
N-tier application c#
You can simplify your class a little for clarity:
public class EmailMailingList
{
public string EmailList { get; set; }
}
Then you have MANY options for getting this info to your db. If you're just starting out, I think plain ol' ADO.Net is a get choice for getting accustomed to things. Something like:
// A method in your code-behind:
public void Save(EmailMailingList list)
{
using(var connection = new SqlConnection("your connection string"))
{
var command = connection.CreateCommand();
command.CommandText = "name of your stored procedure";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter( ... ));
command.ExecuteNonQuery();
}
}
Of course, eventually you'll want to look into the powerful ORMs available to you in the .Net world (Entity Framework, NHibernate, LinqToSql)
I would recommend using the entity data model. It is the quickest, easiest way and it is a "best practice." You should get started bu walking through this tutorial:
http://www.asp.net/web-forms/tutorials/getting-started-with-ef/the-entity-framework-and-aspnet-getting-started-part-1
Once you have your datamodel set up using the wizard, then it is really quick and simple to save your data from a form on the code side:
dataModel.dataEntities de;
dataModel.dataTable tbl;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
//Create new entity object and table object
de = new dataModel.dataEntities();
de.Connection.Open();
tbl = new dataModel.DataEntities();
tbl.Field1 = ((TextBox)tbField1).Text.ToString(); ;
tbl.Field2 = ((TextBox)tbField2).Text.ToString(); ;
//Insert the row and save the change to the table
de.AddToDataTable(tbl);
de.SaveChanges();
de.Connection.Close();
}

Categories

Resources