I'm using WPF MVVM trying to figure out what would be the best way to reload my ViewModel (entire View would work as well I suppose).
The data behind my Model is parsed out of a series of flat files stored within a directory. The location of the directory is saved in the .Settings file and can be the user via a popup window.
If the user changes updates the directory they want to use, how can I recreate my ViewModel so that the data being used is what is in the new directory?
I guess it would be akin to changing to a different database while the app is running if that is what I had as a datastore. Currently I show a message asking the user to restart the application.
Here is the important code:
public SignalViewModel()
{
_trafficSignals = new ObservableCollection<TrafficSignal>(DataAccess.TrafficSignalRepository.GetTrafficSignals());
}
public static List<TrafficSignal> GetTrafficSignals()
{
string dataStore = Properties.Settings.Default.SaveLocation;
var signals = new List<TrafficSignal>();
if (Directory.Exists(dataStore))
{
var files = Directory.GetFiles(dataStore, "CP*.SAV");
Array.Sort(files);
foreach (var file in files)
{
signals.Add(LoadFile(file));
}
}
return signals;
}
I would solve this problem with two events:
Implement the INotifyPropertyChanged in the settings.
In the TrafficSignalRepository I would then implement an event (e.g. SaveLocationChanged) which you raise after the PropertyChanged event of the settings was raised for the SaveLocation-Property
Then you can register for the SaveLocationChanged event inside of the ViewModel. In the registered event handler you just call GetTrafficSignals() again, assign the new value to the field and raise the NotifyPropertyChanged event of the ViewModel. The rest should be done for you automatically by data binding.
You can reload the saved settings using
Properties.Settings.Default.Reload();
And then call GetTrafficSignals() again?
Although having said that, I have had some issues in using the Reload method in the past...
Related
I dont know if it is even possible, but is there some way how to "end" page in Windows Phone 8 app?
My problem is that i am using one delegate (to know when is my xml downloaded) on multiple pages. It works fine, but when i open one page, she initialize herself, i go on other page (trough back button) and new page initialize herself too. Everything is fine, but the previous page is still listening to the delegate and it is really big problem. So i need to get the previous page (that closed) into a same state like she was not ever opened.
I will be thankful for any advice (maybe i am thinking in wrong way now, i dont know, maybe the page just have to be de-initialize).
PS: If its necessary i will post the code, but i think it is not. :)
Okey here is some code:
In class whis is downloading XML i have delegate like this:
public delegate void delDownloadCompleted();
public static event delDownloadCompleted eventDownloadCompleted;
This class is downloading few different xml files depends of constructor in run(int number) method.
After is download complete and all information from xml are saved in my local list i call delegateCompled. if (eventDownloadCompleted != null)
{
eventDownloadCompleted();
}
Then i have few different pages. All pages are used for display specific data from downloaded xml. So on this specific page I have method that is fired when "downloadClass" says it is complet.
XML_DynamicDataChat.delDownloadCompleted delegMetoda = new XML_DynamicDataChat.delDownloadCompleted(inicialiyaceListu);
XML_DynamicDataChat.eventDownloadCompleted += delegMetoda;
This is that "inicializaceListu" method:
private void inicialiyaceListu()
{
Dispatcher.BeginInvoke(() =>
{
model = new datka();
// object model is just model where i am saving all specific list of informations that i got from xml files.
chatList9 = model.getChat(1);
gui_listNovinky.ItemsSource = chatList9;
gui_loadingGrid.Visibility = Visibility.Collapsed;
});
}
All of these works fine, but when i go back (with back button) and open other specific page with other specific information from other downloaded xml, previous page is still listening for the delegate and inicialiyaceListu() method is still fired everytime i complete download of xml.
So i need to say previous page something like: "hey page, you are now closed! Can you shut the **** up and stop work?!?"
I think that specific delegate for each pages could solve this, but it is not correct programing way.
I solved it nice and easy. It is really simple solution. I just created bool variable and set it false when i go back. In inicializaceListu() i have condition if it is true. If it is true do that stuffs when false do nothing.
I am working from the sample project here: http://www.codeproject.com/Articles/8086/Extending-the-save-file-dialog-class-in-NET
I have hidden the address/location bar at the top and made other modifications but I can't for the life of me manage to disable the button that lets you go up to the parent folder. Ist is in the ToolbarWindow32 class which is the problem. This is what I have at the moment but it is not working:
int parentFolderWindow = GetDlgItem(parent, 0x440);
//Doesn't work
//ShowWindow((IntPtr)parentFolderWindow, SW_HIDE);
//40961 gathered from Spy++ watching messages when clicking on the control
// doesn't work
//SendMessage(parentFolderWindow, TB_ENABLEBUTTON, 40961, 0);
// doesn't work
//SendMessage(parentFolderWindow, TB_SETSTATE, 40961, 0);
//Comes back as '{static}', am I working with the wrong control maybe?
GetClassName((IntPtr)parentFolderWindow, lpClassName, (int)nLength);
Alternatively, if they do use the parent folder button and go where I don't want them to, I'm able to look at the new directory they land in, is there a way I can force the navigation to go back?
Edit: Added screenshot
//Comes back as '{static}', am I working with the wrong control maybe?
You know you are using the wrong control, you expected to see "ToolbarWindow32" back. A very significant problem, a common one for Codeproject.com code, is that this code cannot work anymore as posted. Windows has changed too much since 2004. Vista was the first version since then that added a completely new set of shell dialogs, they are based on IFileDialog. Much improved over its predecessor, in particular customizing the dialog is a lot cleaner through the IFileDialogCustomize interface. Not actually what you want to do, and customizations do not include tinkering with the navigation bar.
The IFileDialogEvents interface delivers events, the one you are looking for is the OnFolderChanging event. Designed to stop the user from navigating away from the current folder, the thing you really want to do.
While this looks good on paper, I should caution you about actually trying to use these interfaces. A common problem with anything related to the Windows shell is that they only made it easy to use from C++. The COM interfaces are the "unfriendly" kind, interfaces based on IUnknown without a type library you can use the easily add a reference to your C# or VB.NET project. Microsoft published the "Vista bridge" to make these interfaces usable from C# as well, it looks like this. Yes, yuck. Double yuck when you discover you have to do this twice, this only works on later Windows versions and there's a strong hint that you are trying to do this on XP (judging from the control ID you found).
This is simply not something you want to have to support. Since the alternative is so simple, use the supported .NET FileOk event instead. A Winforms example:
private void SaveButton_Click(object sender, EventArgs e) {
string requiredDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
using (var dlg = new SaveFileDialog()) {
dlg.InitialDirectory = requiredDir;
dlg.FileOk += (s, cea) => {
string selectedDir = System.IO.Path.GetDirectoryName(dlg.FileName);
if (string.Compare(requiredDir, selectedDir, StringComparison.OrdinalIgnoreCase) != 0) {
string msg = string.Format("Sorry, you cannot save to this directory.\r\nPlease select '{0}' instead", requiredDir);
MessageBox.Show(msg, "Invalid folder selection");
cea.Cancel = true;
}
};
if (dlg.ShowDialog() == DialogResult.OK) {
// etc...
}
}
}
I don't this is going to work. Even if you disable the button they can type ..\ and click save and it will take them up one level. You can't exactly disable the file name text box and maintain the functionality of the dialog.
You'd be better off either using the FolderBrowserDialog and setting it's RootFolder property and asking the user to type the filename in or auto generating it.
If the folder you are wanting to restrict the users to isn't an Environment.SpecialFolder Then you'll need to do some work to make the call to SHBrowseForFolder Manually using ILCreateFromPath to get a PIDLIST_ABSOLUTE for your path to pass to the BROWSEINFO.pidlRoot
You can reflect FolderBrowserDialog.RunDialog to see how to make that call.
Since you want such custom behaviors instead of developing low level code (that is likely yo break in the next versions of windows) you can try to develop your file picker form.
Basically it is a simple treeview + list view. Microsoft has a walk-through .
It will take you half a day but once you have your custom form you can define all behaviors you need without tricks and limits.
I am building an application, which has a form where the user can configure all his settings. When the application is loaded, the previously configured settings should reflect to the GUI (The UI should be consistent to the saved settings).
What I am currently doing is creating the settings on the project properties and I have a LoadSettings() method, which gets the values and outputs them to each component on the UI.
The thing is that this is getting VERY messy, and I don't like it at all.
So, that got me wondering, what are the correct approaches to achieve what I want, but yet getting high quality code? Any patterns for that?
private void LoadConfigs()
{
checkBoxStartOnStartup.Checked = ExistKeyValue(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "Wallbase Downloader");
checkBoxCheckWallbaseOnline.Checked = Settings.Default.CheckWallbaseOnlineStartup;
comboBoxResolution.SelectedIndex = comboBoxResolution.FindStringExact(Settings.Default.Resolution == string.Empty
? GetScreenResolution()
: Settings.Default.Resolution);
comboBoxCondition.SelectedIndex = Settings.Default.ConditionIndex;
textBoxWallpaperFolders.Text = Settings.Default.WallpaperFolder;
numericChangeInterval.Text = Convert.ToString(Settings.Default.ChangeIntervalValue);
comboBoxChangeInterval.SelectedIndex = Settings.Default.ChangeIntervalIndex;
numericCheckInterval.Text = Convert.ToString(Settings.Default.CheckIntervalValue);
comboBoxCheckInterval.SelectedIndex = Settings.Default.CheckIntervalIndex;
numericWallpapersToLookFor.Text = Settings.Default.WallpapersToLookFor.ToString();
}
Well, WinForms are not the cleanest framework around...
What you could do is to load all settings when your application starts up and store them in some storage that is available to all forms, e.g. in a static property in a helper settings class.
You can then access that static property from each form when it loads and make all necessary changes to the form based on the settings.
You can use a Hashtable and use English strings for key to make your code really readable. Then serialize it to file on exit and deserialize it back when application loads. Save the serialized file to some common location so that you do not lose it.
This is more of a theory question than anything else, can't really show much in the way of code. However the topic is C# WPF.
So I have an application beginning with a main menu where I set a bunch of variables and load in some data from files and so on ready to begin the main program. I want this to be available to the main window that is going to be opened up.
Currently in my application I have it all set up by data context, an attempt at MVVM which I am very new to. This data context is linked to the menu window and allows me to set all the necessary data.
But how do I go about making that available to the new window. As far as I am aware a new data context is like a new object but in xaml, so if I were to create a data context in the next window all the information from it would be different?
I have always had trouble with things like this in all my learning of programming, I have data in one place but there is no sound way to link it across multiple windows/classes/objects etc.
Currently I have 4 files:
1 Holding all the data classes
2 My 'ViewModel' where I have the objects of these classes, property
updates, not too much
3 My menu with the bindings and data context and its code behind which is empty apart from some button
clicks
4 The main window that is going to use the data <-- this is my problem
First of all is this a correct approach, is there something different I should be thinking about? Can I implement a data context across two windows?
So I set up the context in the mainmenu window:
<Window.DataContext>
<local:WindowFunction x:Name="Interface"/>
</Window.DataContext>
And this links in my between file which has objects of the data.
class WindowFunction
{
protected PortInfo settings = new PortInfo();
protected FileInfo import = new FileInfo();
protected ObservableCollection<PersonName> lanes = new ObservableCollection<PersonName>();
public ObservableCollection<PersonName> Lane
{
get { return lanes; }
set { lanes = value; }
}
public PortInfo Settings
{
get { return settings; }
set { settings = value; }
}
public FileInfo Import
{
get { return import; }
set { import = value; }
}
}
I want to be able to call the information from this in another window. But if I create a new context the property paths will be pointing somewhere else surely?
I'm attempting to build a Windows program that would provide a folder-bookmarks-ish functionality, that would allow you to hit a hotkey and navigate the dialog you have open to the folder assigned. Of course, to do this I'd need to be able to manipulate Windows Explorer dialogs and such. Anyone able to point me in the right direction?
Thanks in advance. :)
Looks like you will need to use pinvoke and get into the nitty gritty but it can be done.
http://www.codeproject.com/Articles/19566/Extend-OpenFileDialog-and-SaveFileDialog-the-easy
I added a reference to SHDocVw Described Here: StackOverflow SHDocVw Example:
This will allow you to enumerate all of the open iexplore windows. (including the open Windows Explorer Dialogs; only issue is for certain special folders the full path is not displayed, but this can be remedied with a little creative code) You can then look through all of the open windows for URLs that have File:/// at the beginning, and then you can prompt the user to assign a hotkey for that specific open window. I've found that the SHDocVw does not reliably return all iexplore windows all the time, so this may not be the exact solution you are looking for. It would be easier to have the user type in the path of the Folder into a textbox on the Form, and then click a button that dynamically created a global hotkey and an event handler for the global hotkey keyboard hook. I attempted this a few different ways, and I ended up using a .cs file on codeproject Here: CodeProject: Low Level Global Keyboard Hook
Within the event Handler for the Global Keyboard Hook, you will have to use Process.Start(x.Process), where x is of a custom class type that has the specific hotkey associated with a specific Folders Location. That way you can look at the key that was pressed in the event handler, and start the associated Process (or in this case, open the specific folder) Each time the user adds an additional folder's location, a new object of custom type is created which includes the hotkey parameter and the folders Path (a user generated value). This custom object type (defined below) is then added to a global list of type "folderLocation" such that it can be accessed later when keys are actually pressed. The application added each folderLocation object to the flList as they were created.
I also defined a List of type Keys and then defined the first 12 objects in this list as F1...F12. For each folderlocation that is added, the next Key in the pre-defined list is added as the hotkey. (although you could also have the user define the hotkey)
In the end, the user presses F1, and the result is that the global key press event handler fires, and then the handler looks to see what button was pressed, compares it to the existing List of custom Types: folderLocation, and looks for a matching Key. Once Found, it then starts the associated folderLocation path using Process.Start.... Good Luck...
public class folderLocation
{
public string folderPath { get; set; }
public string folderName { get; set; }
public Keys hotKey { get; set; }
}