Making a simple database-like program with C#/WPF - c#

I'm working on making a small independent game, and I've reached the point where I'm storing data in XML files, and I'd like to be allow the non-programmers on my team to edit them easily via a GUI, which I'd like to put together with WPF and C#.
I have plenty of experience with C#, but barely any with WPF.
The program would have the following class:
class Foo {
public string Name;
public int Age;
public Foo(string name, int age) {
Name = name;
Age = age;
}
}
And the "database" would just be a
public List<Foo> FooList = new List<Foo>();
What I'd like to make, simplified, is a window with a ListBox on the left side, with "add" and "delete" buttons beneath it (to add and delete items to and from the FooList). The ListBox should have all of the entries in FooList (displaying their Name). On the right side of the window should be a field for Name and Age, and probably some kind of "Save" button.
Now, I could hack this together myself, and I was just about to, when I learned about the existence of data binding. I have no idea how it works (other than that it seems to let you bind controls to variables or something), but it seems like it would make making this a lot easier, right?
I apologize in advance if this seems like too much of a "do everything for me"-type question. I barely know WPF at all, like I said earlier, but I can, for example, handle the serialization and file saving parts myself. I just have no clue how data binding works and how to implement it into my situation (assuming this is even what I want to do).
Thanks in advance!

Here's Microsoft's official WPF databinding tutorial. There's a lot here. And there are many similar tutorials all over the intertubes waiting for you just a google search away. http://msdn.microsoft.com/en-us/library/ms752347.aspx

Simple answer, use XML Notepad to edit XML. It's lightweight enough for non programmers.
http://www.microsoft.com/en-us/download/details.aspx?id=7973

Related

How can I pull a string from a separate class while keeping the class in a list in my main (C#, Unity)

I feel like I should preface this by saying, I am still a beginner and knowing me, I could very well be forgetting something that is ridiculously simple and over complicating in the process. But nonetheless, I have been unable to figure this out.
I’m trying to create a dialogue system in unity that displays a string of text as well as a sprite. However, I am not sure how to pull the string from a separate class while also ensuring that I can keep the class in a list so I can cycle through the text and sprite together. Currently the class I'm attempting to pull from looks like this:
public class DialogueInfo
{
public Sprite emotion;
public string Words;
}
The list looks like this:
public List<DialogueInfo> dialogueInfo = new List<DialogueInfo>();
And I'm trying to use the "Words" string here:
NPC.dialogLines = dialogueInfo.Words;
This however, does not work. I am getting an error saying that "'List<dialogueHolder.DialogueInfo>' does not contain a definition for 'Words' and no accessible extension method..." Any suggestions? This whole process could be a very bad way of doing things and if so, suggestions would be appreciated. If more context is needed, I will gladly provide it.
Note: by using a list i am just trying to keep a format that looks like this: Unity's formatting of a list/array but with both text and a sprite in a single element If I have to use a different approach then that is alright.
Your variable name dialogInfo is misleading. It's not a dialogInfo, it's a box (a list) where there is a lot of dialogInfo inside.
Let's call it dialogInfoList instead.
public List<DialogueInfo> dialogueInfoList = new List<DialogueInfo>();
Extract all the words
If you want to get all the "Words" properties of all the element, you can use linq for this:
NPC.dialogLines = dialogueInfoList.Select(dialogInfo => dialogInfo.Words);
Depending on the type of NPC.dialogueLines (List for instance), you may want to add .ToList() after the Select().
Simpler: just link all the original list
You mentioned you might miss something simpler.
It really depends on what you want to achieve, the quesiton is not very clear about that, but what about keeping all the "DialogInfo" list with the NPC object instead?
Something like:
NPC.DialogueInfoList = dialogueInfoList;
With DialogueInfoList being a property / field of type List<DialogueInfo>

Setting up SpecFlow to pass in identifiers

I am new to C# and am trying to use SpecFlow as I used to use Gherkin by giving a unique name to an item and then passing in the name in the Step Definition. My question is about how to add in the identifier when I create an object so I can call the object without having to pass in the actual name of the object every time that I create a step.
So, for instance the code would look something like this:
[When(#"I click the (.*) button")]
public void ClickTheButton(string ButtonName)
{
driver.Click(ButtonName)
//ButtonName would be a string that would call to the ID for the ADD button
}
I want to be able to put in something like "Add" (so the line would read "When I click the ADD button") and then have the code search for the "ADD" identifier.
I know that this is possible in Ruby/Cucumber by using a DOM and then passing in XML with gherkin names. In Ruby/Cucumber the object would look something like this:
<button gherkin_name="ADD" key="id" value="add_button_12685"/>
However, I am finding absolutely no way of doing that in C# with SpecFlow and this is something that I really need to be able to do.
Is there a way to do this at all? All I'm really trying to do is link a handle/parameter name that business users could actually use to a Page Object like you can in Ruby/Cucumber without making the user know the code in the background. And, incidentally, the names of the objects are almost exactly like the gherkin line that I added in, thus they are very weird to have a user write. This is the reason that I'd like to have just an identifier for the user.
Thanks in advance for your help.
EDIT: I realise now I was not clear enough in my original post so perhaps some background will help. I am using Selenium-Webdriver to test a website that has hundreds of items on it. Writing a different step for every single item on every single page would be exceedingly tedious and time consuming. Because there are many of the exact same items with the exact same characteristics (for instance there are something like 50 buttons that all behave similarly on a single page and the site is dozens of pages) on the pages, writing a single method for testing them seems the most logical idea. Identifying these items with an identifier that the business could use would cut down on bulk inside of the Steps, the number of steps written, and the likelihood that the business users would feel comfortable using the code which is the end goal.
You can do what you want if you are using the PageObject pattern and have a property Buttons (probably on a base PageObject class) which exposes the available buttons as a collection (which can be done via reflection) and then you can just do something like:
[When(#"I click the (.*) button")]
public void ClickTheButton(string ButtonName)
{
myPage.Buttons.First(button=>button.Name==ButtonName).Click;
}
but I would take what AutomatedChaos said into consideration and not use this in a step in the gerkin but just have this as a helper method something like this
[When(#"I add a widget")]
public void AddAWidget(string ButtonName)
{
ClickTheButton("Add")
}
private void ClickTheButton(string ButtonName)
{
myPage.Buttons.First(button=>button.Name==ButtonName).Click;
}
your Buttons property doesn't have to be done with reflection, the simplest implementation is something like this:
public IEnumerable<IWebElement> Buttons
{
yield return AddButton;
yield return RemoveButton;
yield return SomeOtherButton;
//etc etc
}
but using reflection will mean that as you add buttons to the page object you don't need to remember to add them to this method, they will be found automatically.
SpecFlow is only the BDD framework. It will not drive browsers itself, you need to install additional packages that drives the browser.
With C#, you have a few options:
Selenium, the best known and works with the Page Object you are accustomed with.
Fluent Automation, an upcoming library that works as a wrapper on top of Selenium, and makes the interfacing easier (more natural language)
CodedUI, Microsofts web and UI test solution that comes natively with Visual Studio Test edition.
On a personal note, I consider Selenium (with or without Fluent Automation) the best fitted to work with SpecFlow (comparisson)
If you want to install Selenium or other packages, you can install the NuGet package manager to easily search, install and update packages for you.
Lastly, have you considered to use more domain specific Gherkin phrases like When I add a Wabberjock instead of When I press the Add button? This is where the power of BDD lies: Exposing the intention while hiding the implementation details.

differences viewer control in .NET

I have a challenging question. My requirement is like i have a xml file which has values like
Name 0,20
age 21,4
This is like field names values will be there in the following position. I have 100 records like this in my xml file. I want to dynamically read this xml file which is the layout. and to compare two output files generated by two different companies. Output1 and Output2... where the values for Name at the position and age at the position will be there. I want to read the values and manually show the user that there is a differences in the two files at these areas.
Is there any dynamic viewer control available in .net, C# windows , wpf app to display these differences in two files?
this is not a control but a full file difference tool written in c#. Source code is available as well(CharityWare).
http://www.menees.com/
You can see the source code to see how the file difference is implemented.
One of several possible solutions that come to my mind is:
Use XPathNavigator to parse those 3, in practice, files and compare their content.
For visualization use WPF RichTextBox, were you can load complete formatted text and format/color part of it, which you can use for highlighting the differnces found.
WPF RichTextBox Sample1
WPF RichTextBox Sample2
You need to consider that the WPF TextBox is, basically, easy to use but also addicted to consume a lot of memory, so keep an eye on the memory consumption of your app.
There are, naturally other editors, that you can use, like Scintilla, but I think the story in this case become more complicated.
EDIT:
There could be another non programming solution, is just using WinMerge and run that program (which is free) with required parameters. So it will care about showing/highlighting the differences found between 2 different files.
Choice is up to you.
The existing DataGrid class in WPF will meet this need nicely if you design a class like...
public class Difference
{
public string PropertyName { get; set; }
public string File1Value { get; set; }
public string File2Value { get; set; }
}
This class would hold the differences. You would create an instance of this class each time you found a difference you wanted the user to see, and you would add each instance to a collection...
public ObservableCollection<Difference> Differences = new ObservableCollection<Difference>();
And this collection would be bound to the ItemsSource property of the DataGrid.
Using this approach, you would not need to create a new control or use a 3rd party control. If you wanted to tart up the column headers, you can use DataGridColumns and Templates to that end.

ASP.Net MVC 2: Using a viewmodel destroys my model binding

I guess this is a story of how frameworks cheerfully do 95% of what you need, but then frown disapprovingly at that final five percent; inform you that if you want to participate in nonstandard malarky it's your own business, thank you very much, and it'll be here if you decide you want to return to doing things it's good at. Generally speaking it's inevitable that this final five percent will contain some version of a must-have feature.
I have a strongly-typed view which updates a data object. I've used idiomatic MVC2 helpers, eg Html.TextBoxFor(model = > model.Name). I've used Editor templates for nested objects. (My backend is a collection of Mongo documents, so I need to represent complex types).
Then I need a dropdown. It turns out dropdowns are a bit finicky; no problem, I'll make a viewmodel instead of passing in the item directly:
class itemViewModel
{
...
public Item item { get; set; }
public IEnumerable<SelectListItem> dropdown { get; set; }
}
public ActionResult()
{
return View("Update", new itemViewModel(item, dropdown))
}
... that works fine, the dropdown populates. But! my view requires updating:
Html.TextBoxFor(model => model.Name) ->
Html.TextBoxFor(model => model.item.Name)
Great, problem solved. Oops, now my model binding doesn't work. I debug and look at the Request.Form values: Oh. item.Name instead of Name. Makes sense. I tell my Update view to expect an itemViewModel instead, and the binding works.
Oh wait, no it doesn't. Because I have nested objects that use editors. They are strongly typed and they don't know that the model they're receiving is actually a property of the viewmodel. So they're still spitting out Address.City instead of item.Address.City, and the binding fails.
I can think of several workarounds:
Write specialized custom model binder
Put the whole damn form into its own typed editor, so it gets the item model without knowing it's a property
Kill the viewmodel and hack the dropdown using the ViewData dictionary
Quit using the HtmlHelpers and hand-write the whole form
Write my own HtmlHelper extensions that will take a lamba and a model object as parameters.
Put every label/field grouping into an individual editor template.
All of these feel like either overkill or sloppiness. Viewmodels seem to be a clean, helpful approach. Does using them mean that I have to be sloppy in other areas, or reproduce minor variations on sizeable chunks of the framework? I taught myself C# over the last three months (a graphic designer trying to figure out what the hell static typing is with no CS background was probably pretty funny to watch). I work in isolation; there's no one to learn best practices from. I feel like if I don't learn some of them, I'll end up with an unmaintainable dung heap. So, your opinions are appreciated.
Sigh. A couple more hours of Googling and a few shots in the dark, and it appears that there is an unbelievably straightforward way for doing this, using the Bind attribute:
[HttpPost]
public ActionResult([Bind(Prefix="item")] item)
{
//item's complex types populate correctly
}
The attribute seems to be smart enough to reach into the complex types.
I will leave this as a tribute to my own ignorance, and in hopes that some other hapless n00b will find an answer quicker than I did.
Daniel, first off I should say that I commend you on your efforts and taking on .NET , C# and ASP.NET MVC all in one big bite. Ok, so you're frustrated and I relate to that. It's happens to all of us every now and then.
I should let you know that I'm not a fan (not in the least bit, in fact) of ASP.NET MVC (Problems with ASP.NET MVC Framework Design) and so I can't give you a worked out solution to your problem. But here is how I'd like you to see the situation you're in:
You're in a maze and you've made one wrong turn somewhere and you're going deeper into the maze but you're not going to find a way out. So what you need to do is back out till that wrong turn and see if there is another route. So starting from where you are, ask yourself, "why" for every step/change you've made and back up one step at a time asking why. does that make sense? you'll eventually get to a point where you have other alternative ways to tackle the same (original) problem.

Centralizing Messagebox handling for application

I'm wondering how others deal with trying to centralize MessageBox function calling. Instead of having long text embedded all over the place in code, in the past (non .net language), I would put system and application base "messagebox" type of messages into a database file which would be "burned" into the executable, much like a resource file in .Net. When a prompting condition would arise, I would just do call something like
MBAnswer = MyApplication.CallMsgBox( IDUserCantDoThat )
then check the MBAnswer upon return, such as a yes/no/cancel or whatever.
In the database table, I would have things like what the messagebox title would be, the buttons that would be shown, the actual message, a special flag that automatically tacked on a subsequent standard comment like "Please contact help desk if this happens.". The function would call the messagebox with all applicable settings and just return back the answer. The big benefits of this was, one location to have all the "context" of messages, and via constants, easier to read what message was going to be presented to the user.
Does anyone have a similar system in .Net to do a similar approach, or is this just a bad idea in the .Net environment.
We used to handle centralized messages with Modules (VB). We had one module with all messages and we call that in our code. This was done so that we change the message in one place (due to business needs) and it gets reflected everywhere. And it was also easy to handle change in one file instead of multiple files to change the message. Also we opened up that file to Business Analysts (VSS) so that they can change it. I don't think it is a bad idea if it involves modules or static class but it might be a overkill to fetch it from DB.
HTH
You could use resource files to export all text into there (kinda localization feature as well). Resharper 5.0 really helps in that highlighting text that can be moved to resource.
Usually it looks like this:
Before: MessageBox.Show(error.ToString(), "Error with extraction");
Suggestion: Localizable string "Error with extraction"
Right click Move to Resource
Choose resource file and name (MainForm_ExtractArchive_Error_with_extraction), also check checkbox Find identical items in class ...
Call it like this MessageBox.Show(error.ToString(), Resources.MainForm_ExtractArchive_Error_with_extraction);
Best of all it makes it easy to translate stuff to other languages as well as keeping text for MessageBox in separate Resource. Of course Resharper does it all for you so no need to type that much :-)
I suppose you could use a HashTable to do something similar like this, this can be found in:
using System.Collections;
To keep it globally accessable i was thinking a couple of functions in a class holding the hashtable to get/set a certain one.
lets see now.
public class MessageBoxStore
{
private HashTable stock;
public string Get(string msg)
{
if (stock.ContainsKey(msg))
return stock[msg];
else
return string.Empty;
}
public string Set(string msg, string msgcontent)
{
stock[msg] = msgcontent;
}
}
or something like that, you could keep multiple different information in the hashtable and subsequently compose the messagebox in the function too.. instead of just returning the string for the messagebox contents...
but to use this it would be quite simple.
call a function like this on program load.
public LoadErrorMessages()
{
storeClass = new MessageBoxStore();
storeClass.Set("UserCantDoThat", "Invalid action. Please confirm your action and try again");
}
for example, and then.
MessageBox.Show(storeClass.Get("UserCantDoThat"));
i put this in a new class instead of using the HashTable get/set methods direct because this leaves room for customization so the messagebox could be created in the get, and more than 1 piece of information could be stored in the set to handle messagebox title, buttontype, content, etc etc.

Categories