Change referenceequals to equals in reference.cs - wpf

I have a wpf app that uses a wcf webservice. Its my webservice and app, so I can make changes to either side. In the Reference.cs file that gets automatically genereated by visual studio it uses this code for the property changed event:
[System.Runtime.Serialization.DataMemberAttribute()]
public string Value {
get {
return this.ValueField;
}
set {
if ((object.ReferenceEquals(this.ValueField, value) != true)) {
this.ValueField = value;
this.RaisePropertyChanged("Value");
}
}
}
For strings though what I would really like is this:
[System.Runtime.Serialization.DataMemberAttribute()]
public string Value {
get {
return this.ValueField;
}
set {
if ((object.ReferenceEquals(this.ValueField, value) != true)) {
if (this.ValueField != value)
{
this.ValueField = value;
this.RaisePropertyChanged("Value");
}
}
}
}
That way the property changed event would not go off if the value is the same. Why this is an issue is because I listen to the OnPreviewTextInput of a textbox and change the value programmatically, then the event goes off twice, once because I changed it and once because wpf changed it via binding.
Thanks,

If you control both the server and the client, you can define your type in a seperate assembly, which you then reference from both projects.
In the WCF reference add dialog advanced settings you can tell it to re-use types, then it will use whatever implementation of your data object exists in the common assembly on the client.

Related

Windows 10 Universal App - ListView Update from Background Thread

I have a strange problem here. We develop a Windows 10 Universal App and now I want to update my listview when I add new value. But unfortunately it wont work and I dont really know why. When I add new value it won't update my list view.
The data comes from a background-thread (REST-Request against Server) and therefore I know, I should use something that runs the "add-functionality" on the UI-Thread.
First of all I declared a IProgress and my collection:
private List<dtoGemeinde> _listeGemeinden = new List<dtoGemeinde>();
public List<dtoGemeinde> GemeindenCollection
{
get { return this._listeGemeinden; }
}
IProgress<dtoGemeinde> prog;
prog = new Progress<dtoGemeinde>(UpdateListViewUI);
This is the "UpdateListViewUI" method:
public void UpdateListViewUI(dtoGemeinde dto)
{
_listeGemeinden.Add(dto);
this.listViewGemeinden.ItemsSource = GemeindenCollection;
}
And this is the callback method which is called when the background thread, which loads the data from the server, is finished:
public async void onCallBackGemeinden(List<dtoGemeinde> listeGemeinden)
{
if (listeGemeinden != null && listeGemeinden.Count > 0)
{
this.progress.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
foreach (dtoGemeinde dto in listeGemeinden)
{
await listViewGemeinden.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () => prog.Report(dto));
}
}
else
{
await new MessageDialog("Data cant be load", "Error").ShowAsync();
}
}
ObservableCollection instead of List usually works fine if need to bind a ListView and be able to see the updates, if this doesn't work any underlying class might need to implement the INotifyChanged pattern to update any properties within the collection if needed.

Is a Value changed through Input?

How do I know when is a value of any control changed by user input (interaction with mouse or keyboard)?
Any suggestions? Is there a common way for this?
EDIT:
I am seeking for attached property or extending already given controls or whatever is needed just to get notified whether user input is taking place at the time value is changed. eg ComboBox SelectedItem changed by user input (User could enter text or select an item in drop down menu)
Its pure View thing therefore I am sorry but no ViewModel solutions for this issue will be accepted.
The simplest way would simply be to register to the Binding.TargetUpdated event, which is fired when the UI-side is updated (while Binding.SourceUpdated is fired when the ViewModel-side is updated)
Use a property with backing field in your view model. Introduce a second setter - a SetProp() method - that you use inside your ViewModel. That way you can add different behavior, depending on the origin of the call.
```
private bool mMyProp;
public bool MyProp
{
get { return mMyProp; }
set
{
if (mMyProp != value)
{
mMyProp = value;
// Todo: add here code specific for calls coming from the UI
RaisePropertyChanged(() => MyProp);
}
}
}
public void SetPropFromViewModel(bool value)
{
if (mMyProp != value)
{
mMyProp = value;
// Todo: add here code specific for calls coming from ViewModel
RaisePropertyChanged(() => MyProp);
}
}

Pattern for binding commands on a child ViewModel from a parent menu

I'm creating a WPF MVVM app using Caliburn Micro. I have a set of buttons in a menu (Ribbon) that live in the view for my shell view model, which is a ScreenConductor. Based on the currently active Screen view model, I would like to have the ribbon buttons be disabled/enabled if they are available for use with the active Screen, and call actions or commands on the active Screen.
This seems like a common scenario. Is there a pattern for creating this behavior?
Why don't you do the reverse thing, instead of checking which commands are supported by the current active screen, let the active screen populate the menu or ribbon tab with all the controls that it supports, (i would let it inject its own user control which might just be a complete menu or a ribbon tab all by itself), this will also enhance the user experience as it will only show the user the controls that he can work with for the current active screen.
EDIT: Just looking at your question again and I'm thinking that this is much simpler than it looks
The only issue I can see you having is that a lack of a handler (and guard) method on a child VM will mean that buttons that don't have an implementation on the currently active VM will still be enabled.
The default strategy for CM is to try and find a matching method name (after parsing the action text) and if one is not found, to leave the button alone. If you were to customise that behaviour so that the default is for buttons to be disabled, you could easily get it working by just implementing the command buttons in your shell, making sure to set the command target to the active item:
In the shell define your buttons, making sure they have a target that points to the active child VM
<Button cal:Message.Attach="Command1" cal:Action.TargetWithoutContext="{Binding ActiveItem}" />
Then just implement the method in your child VM as per usual
public void Command1() { }
and optionally a CanXX guard
public bool CanCommand1
{
get
{
if(someCondition) return false;
return true;
}
}
Assuming you don't get much more complex than this, it should work for you
I'm going to have a quick look at the CM source and see if I can come up with something that works for this
EDIT:
Ok you can customise the ActionMessage.ApplyAvailabilityEffect func to get the effect you want - in your bootstrapper.Configure() method (or somewhere at startup) use:
ActionMessage.ApplyAvailabilityEffect = context =>
{
var source = context.Source;
if (ConventionManager.HasBinding(source, UIElement.IsEnabledProperty))
{
return source.IsEnabled;
}
if (context.CanExecute != null)
{
source.IsEnabled = context.CanExecute();
}
// Added these 3 lines to get the effect you want
else if (context.Target == null)
{
source.IsEnabled = false;
}
// EDIT: Bugfix - need this to ensure the button is activated if it has a target but no guard
else
{
source.IsEnabled = true;
}
return source.IsEnabled;
};
This seems to work for me - there is no target for methods which couldn't be bound to a command, so in that case I just set IsEnabled to false. This activates buttons only when a method with a matching signature is found on the active child VM - obviously give it a good test before you use it :)
Create methods and accompanying boolean properties for each of your commands on your shell view model. (See code below for an example.) Caliburn.Micro's conventions will wire them up to the buttons for you automatically. Then simply raise property changed events for the boolean properties when you change views to have them be re-evaluated.
For example, let's say you have a Save button. The name of that button in your xaml would be Save, and in your view model, you would have a Save method along with a CanSave boolean property. See below:
public void Save()
{
var viewModelWithSave = ActiveItem as ISave;
if (viewModelWithSave != null) viewModelWithSave.Save();
}
public bool CanSave { get { return ActivateItem is ISave; } }
Then, in your conductor, whenever you change your active screen, you would call NotifyOfPropertyChange(() => CanSave);. Doing this will cause your button to be disabled or enabled depending upon if the active screen is capable of dealing with that command. In this example, if the active screen doesn't implement ISave, then the Save button would be disabled.
I would use the Caliburn.Micro event aggregation in this scenario, as follows:
Create a class named ScreenCapabilities with a bunch of Boolean attributes (e.g. CanSave, CanLoad, etc.)
Create a message named ScreenActivatedMessage with a property of type ScreenCapabilities
Create a view model for your ribbon that subscribes to (handles) the ScreenActivatedMessage
In the ribbon view model's Handle method, set the local CanXXX properties based on the supplied ScreenCapabilities.
It would look something like this (code typed by hand, not tested):
public class ScreenCapabilities
{
public bool CanSave { get; set; }
// ...
}
public class ScreenActivatedMessage
{
public ScreenCapabilities ScreenCapabilities { get; set; }
// ...
}
public class RibbonViewModel : PropertyChangedBase, IHandle<ScreenActivatedMessage>
{
private bool _canSave;
public bool CanSave
{
get { return _canSave; }
set { _canSave = value; NotifyPropertyChanged(() => CanSave); }
}
// ...
public void Handle(ScreenActivatedMessage message)
{
CanSave = message.ScreenCapabilities.CanSave;
// ...
}
}
Then, somewhere appropriate, when the screen changes, publish the message. See see Caliburn.Micro wiki for more info.
Define a property (let's say ActiveScreen) for the active screen in the shell view model.
And let's assume you have properties for the each button such as DeleteButton, AddButton.
Screen is a viewmodel for the screens.
private Screen activeScreen;
public Screen ActiveScreen
{
get
{
return activeScreen;
}
set
{
activeScreen= value;
if (activeScreen.Name.equals("Screen1"))
{
this.AddButton.IsEnabled = true;
this.DeleteButton.IsEnabled = false;
}
if else (activeScreen.Name.equals("Screen2"))
{
this.AddButton.IsEnabled = true;
this.DeleteButton.IsEnabled = true;
}
NotifyPropertyChanged("ActiveScreen");
}
}

Linq to Sql - How to update an object using a repository pattern?

There is tons of information on this, but even after reading for hours and hours I can't seem to get this to work the way I want.
I'm trying to update a User object by passing in a User object and generically comparing changes to a User object I pull out of the database. I always end up getting the NotSupportedException when using this method:
An attempt has been made to Attach or
Add an entity that is not new, perhaps
having been loaded from another
DataContext. This is not supported.
Here is how I am trying to do it:
public void SaveUser(User User)
{
using (DataContext dataContext = new DataContext(WebConfigurationManager.ConnectionStrings["database"].ConnectionString))
{
// New user
if (User.UserID == 0)
{
dataContext.Users.InsertOnSubmit(User);
}
// Existing user
else
{
User dbUser = dataContext.Users.Single(u => u.UserID.Equals(User.UserID));
Type t = dbUser.GetType();
foreach (PropertyInfo p in t.GetProperties())
{
if (p.CanWrite & p.GetValue(dbUser, null) != p.GetValue(User, null))
{
p.SetValue(dbUser, p.GetValue(User, null), null);
}
}
//dataContext.Refresh(RefreshMode.KeepCurrentValues, dbUser);
}
dataContext.SubmitChanges();
}
}
The commented out line I tried uncommented too, but it was no help.
If I comment out the foreach() loop and add a line like dbUser.UserName = "Cheese"; it will update the User's name in the database fine. That leads me to believe it is something with how the foreach() loop changing the dbUser object that causes this to fail.
When I debug the dbUser object, it appears to correctly acquire all the changes from the User object that was passed as an argument.
I also did some reading on optimistic concurrency and added a column to the table of data type timestamp, but that didn't seem to have any effect either.
What exactly am I doing wrong here?
How can I get this to generically detect what has changed and correctly persist the changes to the database?
My guess is there's a foreign key relation that you are trying to copy over that was not initially loaded (because of lazy-loading) During the copying, it's attempting to load it, but the DataContext has already been disposed.
I've been working on a similar problem. I ended up using AutoMapper to handle copying the properties for me. I have configured AutoMapper to ignore the primary key field as well as any relations. Something like:
public void Update(User user)
{
using (var db = new DataContext(...))
{
var userFromDb = db.Users.Where(x => x.Id == user.Id).Single();
AutoMapper.Mapper.Map(user, userFromDb);
db.SubmitChanges();
}
}
My automapper configuration is something like
AutoMapper.Mapper.Create<User, User>().ForMember(dest => dest.Id, opt => opt.Ignore())
.ForMember(dest => dest.SomeRelation, opt => opt.Ignore());
You can find AutoMapper here: http://automapper.codeplex.com/
I keep my repo pretty lean, it's only job is to interact with the database. I build a Service layer on top of the repo that does a little more work
public class EventRepository : IEventRepository
{
private DBDataContext dc;
public EventRepository()
{
dc = new DBDataContext();
}
public void Create(Event #event)
{
dc.Events.InsertOnSubmit(#event);
}
public System.Linq.IQueryable<Event> Read()
{
object events = (from e in dc.Eventse);
return events.AsQueryable;
}
public void SubmitChanges()
{
dc.SubmitChanges();
}
}
Then the corresponding call from the service layer looks like this
public void AddEvent(Event #event)
{
_EventRepository.Create(#event);
}
public void SubmitChanges()
{
_EventRepository.SubmitChanges();
}
And I call it from my controller.
// AutoMapper will allow us to map the ViewModel with the DomainModel
Mapper.CreateMap<Domain.ViewModels.EventsAddViewModel, Domain.Event>();
object #event = Mapper.Map<Domain.ViewModels.EventsAddViewModel, Domain.Event>(eventToAdd);
// Add the event to the database
EventService.AddEvent(#event);
EventService.SubmitChanges();

Winforms: Enabling Localization by default (enforcing a project/solution policy)

Is there an easy way to set the Localizable property to true for newly created usercontrols / forms? The scope of the setting should ideally be a solution or a project.
In other words I want to say that this project/solution should be localizable, and then if I add a new form or control VS should automatically set the property to true.
Edit:
Although custom templates are possible, in a larger team they might not be always used. So it's more about enforcing a policy, ensuring that the team members do not ommit to set the property for the projects/solutions where it is a requirement that all forms/controls containing text resources should be localizable.
Note: Team Foundation Server is not an Option.
Not sure if it is worth the effort for a property that is so easy to change and so easy to see that it has the wrong value. But you can create your own item template.
For example: Project + Add User Control. Set its Localizable property to True. File + Export Template, select Item template. Next. Check the control you added. Next. Check all references, omit only the ones you'll never need. Next. Give it is good template name (say: "Localizable User Control").
You'll now have an item template available for future projects that has the property set. Repeat as necessary for other item templates, like a Form.
It's possible to write a unit test that uses reflection to determine whether a form/user control has been marked as localizable. Specifically, if a type has been marked as localizable, there will be an embedded resource file associated with the Type and that file will contain a ">>$this.Name" value. Here's some sample code:
private void CheckLocalizability()
{
try
{
Assembly activeAssembly = Assembly.GetAssembly(this.GetType());
Type[] types = activeAssembly.GetTypes();
foreach (Type type in types)
{
if (TypeIsInheritedFrom(type, "UserControl") || TypeIsInheritedFrom(type, "Form"))
{
bool localizable = false;
System.IO.Stream resourceStream = activeAssembly.GetManifestResourceStream(string.Format("{0}.resources", type.FullName));
if (resourceStream != null)
{
System.Resources.ResourceReader resourceReader = new System.Resources.ResourceReader(resourceStream);
foreach (DictionaryEntry dictionaryEntry in resourceReader)
{
if (dictionaryEntry.Key.ToString().Equals(">>$this.Name", StringComparison.InvariantCultureIgnoreCase))
{
localizable = true;
break;
}
}
}
if (!localizable)
{
Debug.Assert(false, string.Format("{0} is not marked localizable.", type.FullName));
}
}
}
}
catch (Exception ex)
{
Debug.Assert(false, string.Format("Exception occurred: Unable to check localization settings. {0}", ex.Message));
}
}
private bool TypeIsInheritedFrom(Type type, string baseType)
{
while (type != null)
{
if (type.Name.Equals(baseType, StringComparison.InvariantCultureIgnoreCase))
return true;
type = type.BaseType;
}
return false;
}
Please let me know if this helps.

Resources