I'm setting up a SharePoint 2016 site for a demo and discovered the pages don't display due to an HTTP 500 Internal Server Error. However Central Administration works just fine. Fortunately a Google search lead to this article from Cloudshare that contained the solution for me- https://www.cloudshare.com/blog/cloudshare/http-500-internal-server-error-explanation-how-to-fix It pertains to SP2013, but is exactly the same in SP2016. Basically the SecurityTokenServiceApplicationPool's security context needed to be updated.
Thanks Cloudshare!
Tuesday, July 18, 2017
Saturday, March 25, 2017
WPF/MVVM viewing and editing data in a many-to-many relationship (Part 2 of 2)
This is a continuation of a previous post where I explained my scenario and how I displayed data in a many-to-many relationship. Now I'll explain how I ended up editing and saving. It seems a bit more complicated than it should be, but it works.
Editing
I have two objects named Racers and Divisions. One racer can be in zero or more divisions and one division can contain zero or more racers. I'm editing the relationship on a Racer maintenance form where a racer's divisions are selected in a checkbox list. See the previous post for details.View Model
To accommodate this I have two commands in my Maintain Racer view model, one for adding a division and one for removing a division. And a keep the original list of racer divisions in case the user cancels. Here are the relevant parts of the view model:
private List<Division> _originalRacerDivisions;
public ICommand AddDivisionCommand { get; set; }
public ICommand RemoveDivisionCommand { get; set; }
// Constructor
public RacerDetailViewModel(IDerbyDataService derbyDataService)
{
... snip ...
AddDivisionCommand = new CustomCommand(AddDivision, CanAddRemoveDivision);
RemoveDivisionCommand = new CustomCommand(RemoveDivision, CanAddRemoveDivision);
... snip ...
}
private void LoadRacer(Racer racer)
{
... snip ...
_originalRacerDivisions = racer.Divisions;
... snip ...
}
private void AddDivision(object obj)
{
if (!(obj is Division))
throw new ArgumentException("Invalid division");
var divisionToAdd = (Division)obj;
var racerDivisions = RacerDivisions;
racerDivisions.Add(divisionToAdd);
RacerDivisions = racerDivisions;
}
private void RemoveDivision(object obj)
{
if (!(obj is Division))
throw new ArgumentException("Invalid division");
var divisionToRemove = (Division)obj;
var racerDivisions = RacerDivisions;
racerDivisions.Remove(divisionToRemove);
RacerDivisions = racerDivisions;
}
private bool CanAddRemoveDivision(object obj)
{
return true;
}
}
}
View
In the view I have a template column with a checkbox. I used this instead of a checkbox column because a checkbox column requires two clicks- one to select the row and a second to change the value. This way only one click is needed.
There are two triggers- one handles the Checked event and calls the AddDivision command, and the other handles the Unchecked event and called RemoveDivision command.
There are two triggers- one handles the Checked event and calls the AddDivision command, and the other handles the Unchecked event and called RemoveDivision command.
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5">
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource localDivisionToBooleanConverter}"
Mode="OneWay">
<Binding Path="."></Binding>
<Binding Path="DataContext.RacerDivisions"
RelativeSource="{RelativeSource AncestorType=Window}"></Binding>
</MultiBinding>
</CheckBox.IsChecked>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding DataContext.AddDivisionCommand, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding Path=.}" />
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<i:InvokeCommandAction Command="{Binding DataContext.RemoveDivisionCommand, RelativeSource={RelativeSource AncestorType=Window}}"
CommandParameter="{Binding Path=.}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Cancelling
If the user decides to cancel, the racer's divisions need to be set back to their original values:private void CancelRacer(object obj)
{
racer.Divisions = _originalRacerDivisions;
... snip ...
}
Labels:
Binding,
C#,
Command,
many-to-many,
MVVM,
ObservableCollection,
WPF
Thursday, March 16, 2017
WPF/MVVM viewing and editing data in a many-to-many relationship (Part 1 of 2)
In the WPF/MVVM world some things seem to be a lot more complicated than they should be. One of those things is presenting and editing data in a many-to-many relationship. Once again, thanks to Google for leading to this article that was the starting point for of my solution- https://social.technet.microsoft.com/wiki/contents/articles/20719.wpf-displaying-and-editing-many-to-many-relational-data-in-a-datagrid.aspx
The corresponding database tables look like this:

These are my model classes. Note that there are just two classes- Racer and Division. The navigation properties (Racer.Divisions and Divisions.Racers) are the link between them and are equivalent to the RacerDivisions link table in the database.
Like the TechNet article, I am showing all the Divisions in a DataGrid with a check box column representing the divisions the racer is a member of (ie. is linked to). So in my viewmodel I expose a list of all Divisions and a list of the Racer's Divisions (from the Racer object's graph- Racer.Divisions). Here are the relevant viewmodel snippets:
The checkboxes need a boolean value to bind to. I have a converter for this that takes two parameters: a Division object and a list of Racer.Divisions. If Racer.Divisions contains the Division, it returns True, and if not- False.
And finally, the WPF DataGrid that shows the data. It is bound to the list of all Divisions. I put the checkboxes in a template column because in a regular checkbox column the checkbox has to be clicked twice to change its value. The current division and list of Racer's divisions are passed to the converter to populate the row's checkbox.
And there you have it! Next I'll explain how the data is edited and saved. That will be in a new post because this one is long enough.
My Scenario
I have two objects named Racers and Divisions. One racer can be in zero or more divisions and one division can contain zero or more racers. The data is edited on a Racer maintenance form that looks like this:The corresponding database tables look like this:

These are my model classes. Note that there are just two classes- Racer and Division. The navigation properties (Racer.Divisions and Divisions.Racers) are the link between them and are equivalent to the RacerDivisions link table in the database.
public class Racer : ModelBase, IModificationHistory
{
public Racer()
{
Divisions = new List<Division>();
}
private int racerId;
private int carNumber;
private string carName;
private string ownerLastName;
private string ownerFirstName;
private List<Division> divisions;
private DateTime dateModified;
private DateTime dateCreated;
public int RacerId
{
get { return racerId; }
set
{
if (value == racerId) return;
racerId = value;
RaisePropertyChanged("RacerId");
}
}
// The other getters/setters here
}
public class Division : ModelBase, IModificationHistory
{
public Division()
{
Racers = new List();
}
private int divisionId;
private int sequence;
private string name;
private string logoPath;
private bool includeInChampionship;
private bool isChampionship;
private List racers;
private DateTime dateModified;
private DateTime dateCreated;
public int DivisionId
{
get { return divisionId; }
set
{
divisionId = value;
RaisePropertyChanged("DivisionId");
}
}
// The other getters/setters here
}
Showing the Data
public class RacerDetailViewModel : ViewModelBase, IDataErrorInfo
{
private List<Division> _divisions;
private Racer _selectedRacer { get; set; }
// Various properties exposing Racer data to the view
// The list of all Divisions
public List<Division> Divisions
{
get { return _divisions; }
}
// The Racer Instance's Divisions
public ObservableCollection<Division> RacerDivisions
{
get { return _selectedRacer.Divisions.ToObservableCollection(); }
set
{
_selectedRacer.Divisions = value.ToList();
SetRacerDirty();
RaisePropertyChanged("Divisions");
}
}
// Other unrelated parts of the viewmodel (constructor, command handlers, etc.)
}
The checkboxes need a boolean value to bind to. I have a converter for this that takes two parameters: a Division object and a list of Racer.Divisions. If Racer.Divisions contains the Division, it returns True, and if not- False.
class DivisionToBooleanConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (!(values[0] is Division))
throw new ArgumentException("DivisionToBooleanConverter- First arg must be Division");
if (!(values[1] is ObservableCollection<Division>))
throw new ArgumentException("DivisionToBooleanConverter- Second arg must be RacerDivisions.");
var division = (Division)values[0];
var racerDivisions = (ObservableCollection<Division>)values[1];
return racerDivisions.Contains(division);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And finally, the WPF DataGrid that shows the data. It is bound to the list of all Divisions. I put the checkboxes in a template column because in a regular checkbox column the checkbox has to be clicked twice to change its value. The current division and list of Racer's divisions are passed to the converter to populate the row's checkbox.
<DataGrid Grid.Row="4" Grid.Column="1" Margin="5" ItemsSource="{Binding Divisions}"
AutoGenerateColumns="False" CanUserAddRows="False" HeadersVisibility="None">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}"></DataGridTextColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5">
<CheckBox.IsChecked>
<MultiBinding Converter="{StaticResource localDivisionToBooleanConverter}"
Mode="OneWay">
<Binding Path="."></Binding>
<Binding Path="DataContext.RacerDivisions"
RelativeSource="{RelativeSource AncestorType=Window}"></Binding>
</MultiBinding>
</CheckBox.IsChecked>
</CheckBox>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
And there you have it! Next I'll explain how the data is edited and saved. That will be in a new post because this one is long enough.
Sunday, March 12, 2017
WPF/MVVM - Validating ViewModels with IDataErrorInfo and models with annotations
I'm working on a personal WPF/MVVM project where I need validations at both the View Model and Model level. For business rule validation I decided to implement the IDataErrorInfo interface in my view models. It works pretty well and it is easy to find examples of how to do it. However in my case I also have basic validations (like required fields, string length limits, etc.) in Annotations at the model level. This is necessary because I'm using Entity Framework 6- Code First to generate my database. The hard part was combining both levels of validation. Here's how I ended up doing it:
All my model classes inherit from a base class that implements INotifyPropertyChanged and IDataErrorInfo. OnValidate returns validation errors from the annotations. Plenty of examples how to do this- just google IDataErrorInfo Annotations.
The implementation in my model classes looks more or less like this:
And then in my view models I also implement IDataErrorInfo. I first perform the view model validations, then if there are no errors I go to the model's IDataErrorInfo's implementations and check for errors there. The basic idea came from http://stackoverflow.com/questions/13113779/implementing-idataerrorinfo-in-a-view-model
And finally, the binding in the view looks like this:
All my model classes inherit from a base class that implements INotifyPropertyChanged and IDataErrorInfo. OnValidate returns validation errors from the annotations. Plenty of examples how to do this- just google IDataErrorInfo Annotations.
public class ModelBase : INotifyPropertyChanged, IDataErrorInfo
{
#region " INotifyPropertyChanged "
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#region " IDataErrorInfo "
public string this[string propertyName]
{
get
{
return OnValidate(propertyName);
}
}
/// <summary>
/// Validates current instance properties using Data Annotations.
/// </summary>
/// <param name=“propertyName”>This instance property to validate.</param>
/// <returns>Relevant error string on validation failure or <see cref=“System.String.Empty”/> on validation success.</returns>
private string OnValidate(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
throw new ArgumentException("Property may not be null or empty", propertyName);
string error = string.Empty;
var value = this.GetType().GetProperty(propertyName).GetValue(this, null);
var results = new List<ValidationResult>();
var context = new ValidationContext(this, null, null) { MemberName = propertyName };
var result = Validator.TryValidateProperty(value, context, results);
if (!result)
{
var validationResult = results.First();
error = validationResult.ErrorMessage;
}
return error;
}
public string Error
{
get
{
throw new NotSupportedException("IDataErrorInfo.Error is not supported, use IDataErrorInfo.this[propertyName] instead.");
}
}
#endregion
}
The implementation in my model classes looks more or less like this:
public class MyClass: ModelBase
{
private string someProperty;
[Required]
[StringLength(255, ErrorMessage = "Some Property maximum length is 255 characters")]
public string SomeProperty
{
get { return someProperty; }
set
{
if (value == someProperty) return;
someProperty= value;
RaisePropertyChanged("SomeProperty");
}
}
}
And then in my view models I also implement IDataErrorInfo. I first perform the view model validations, then if there are no errors I go to the model's IDataErrorInfo's implementations and check for errors there. The basic idea came from http://stackoverflow.com/questions/13113779/implementing-idataerrorinfo-in-a-view-model
public class MyViewModel: IDataErrorInfo
{
private MyClass _myClass { get; set; }
public string SomeProperty
{
get { return _myClass.SomeProperty; }
set
{
_myClass.SomeProperty= value;
RaisePropertyChanged("SomeProperty");
}
}
#region " Implementation of IDataErrorInfo "
public string Error
{
get { throw new NotSupportedException("Not supported"); }
}
// Put business rule validation here
public string this[string propertyName]
{
get
{
if (propertyName.Equals("SomeProperty"))
{
if (SomeProperty == "FooBar")
return "SomeProperty cannot be FooBar.";
}
// If we get to here, ViewModel validation passed. So do the Model validations-
return _selectedRacer[propertyName];
}
}
#endregion
}
And finally, the binding in the view looks like this:
<TextBox Text="{Binding SomeProperty, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True}">
Monday, December 19, 2016
Generic List - Inserting item in the proper order
Happy Whatever Holiday You Are Or Soon Will Be Celebrating! Christmas for me!
Recently I had a requirement to insert a new item in a generic list in the proper order according to two properties in the collection object. The solution I came up with, with the help of some Googling, is:
Recently I had a requirement to insert a new item in a generic list in the proper order according to two properties in the collection object. The solution I came up with, with the help of some Googling, is:
- From the item to be inserted, combine its values for the two properties into a single string.
- Sort the list of generic list of objects in descending order by the the first property, and then the second.
- Find the index of the first item whose combined property values are less than the combined values of the item to be inserted. Add 1 to the index to insert the new item in the next "slot".
- If there are no items with a lesser combined value return 0. I.E. insert the new item first in the list.
public static int CalculateInsertIndex(List<ObjectName> listOfObjects, string propertyValue1, string propertyValue2)
{
var combinedValue = propertyValue1.Trim() + "." + propertyValue2;
// Find the row just below where the new item will be inserted
var timesheetItemToIndex = listOfObjects
.OrderByDescending(t => t.Property1)
.ThenByDescending(t => t.Property2)
.FirstOrDefault(
t => string.Compare((t.Property1.Trim() + "." + t.Property2), combinedValue ,
StringComparison.CurrentCultureIgnoreCase) < 0);
// Return the index of the next item
if (timesheetItemToIndex == null) return 0;
return listOfObjects.IndexOf(timesheetItemToIndex ) + 1;
}
Wednesday, September 7, 2016
SharePoint Foundation 2010 - Access denied for users that have full control
We just hired a new web content editor and while setting her up with access to our intranet website I ran into a bizarre permissions problem. She was granted full control of the site but kept getting access denied on one specific page.
The resolution on this page worked for me- http://underthehood.ironworks.com/2011/05/sharepoint-2010-access-denied-for-users-that-have-full-control-on-the-site.html However in my case I only granted Full Read to the one user instead of all authenticated users.
Perhaps the two people besides me still using SharePoint Foundation 2010 might find this helpful. ;)
The resolution on this page worked for me- http://underthehood.ironworks.com/2011/05/sharepoint-2010-access-denied-for-users-that-have-full-control-on-the-site.html However in my case I only granted Full Read to the one user instead of all authenticated users.
Perhaps the two people besides me still using SharePoint Foundation 2010 might find this helpful. ;)
Monday, May 30, 2016
Visual Studio Live! Austin - Day 4 (Wednesday 5/19/2016)
Finally, a quick rundown of the sessions I attended on the fourth and final day (as best as I can remember):
Role-Based Security Stinks: How to Implement Better Authorization in ASP.NET WebAPI
Great introduction to claims-based authorization, which is apparently going to be the norm in the future. Is a lot more granular than traditional role-based authorization Roles are binary- a user is either in the role (and has its inherent rights) or they're not. With claims a user can be in a role, but only in certain circumstances. For example, a manager can see personnel information only for her employees, but not everyone in the organization. Need to learn about Windows Identity Foundation.
DI Why? Getting a Grip on Dependency Injection
Jeremy Clark is a great speaker and I highly recommend attending his sessions if you ever have the chance. This was a good into to Dependency Injection, which is a design pattern that lets you assign dependency objects at runtime. I don't really have my head around it, but I realize that I need to because it is very closely related to unit testing. Jeremy has a Pluralsight course on the subject that I plan on taking as soon as possible.
User Experience Case Studies - Good and Bad
In the past year or so Billy Hollis has really changed my attitude about UX. It had never really been my interest or forte- I've been a middleware and database guy most of my career. But reading/hearing Billy in blogs and podcasts, seeing the WPF applications he has built, and now seeing him live has been very inspirational. He gave a great overview of US design laws and principles where were new to me, like:
- Hicks Law- Increasing the number of choices will increase decision time
- Fits Law- The closer and bigger something is, the easier & faster it is to get to it.
Exceptional Development: Dealing with Exceptions in .NET
There were three great sessions in this time slot: this one, a Billy Hollis talk on building Windows 10 apps, and a Jeremy Clark talk on clean code. Unfortunately there's only one of me and I chose this one.
Very enlightening- the presenter's recommendations flew in the face of the way I've been handling exceptions most of my career. Basically, don't bother handling exceptions unless you can recover from them. For example, if the app needs to send an email but can't connect to the email server, put the email in a queue and try again later. Otherwise if the exception is bad enough for the app to die, let it die. However, when exceptions occur a much information about them needs to be captured and logged. The presenter discussed various ways to do this in WPF (Windows/UWP apps) and web apps.
Very enlightening- the presenter's recommendations flew in the face of the way I've been handling exceptions most of my career. Basically, don't bother handling exceptions unless you can recover from them. For example, if the app needs to send an email but can't connect to the email server, put the email in a queue and try again later. Otherwise if the exception is bad enough for the app to die, let it die. However, when exceptions occur a much information about them needs to be captured and logged. The presenter discussed various ways to do this in WPF (Windows/UWP apps) and web apps.
Windows 10 Design Guideline Essentials
Another case of multiple sessions I really wanted to attended in the same time slot. I wish some of these would have been Wednesday afternoon where there wouldn't have been as much of a conflict for me.
Most of what was discussed was probably common sense to anyone with a design background, but it as new and interesting to me-
Most of what was discussed was probably common sense to anyone with a design background, but it as new and interesting to me-
- group related things to gather visually
- rounded things look more pleasant
- larger buttons draw attention
- less clutter is calming, try to make layouts open and not as crowded
Overall thought about the conference
A massive amount of great information to take in in a short amount of time. I highly recommend attending if you're in the .NET space.
Saturday, May 21, 2016
Visual Studio Live! Austin - Day 3 (Wednesday 5/18/2016)
If I ever attend another conference like this I'll blog about it the same day. It was a lot of information to take in over 4 days and some details are getting lost in the fog.
Angular 2 101
Deborah Kurata, Ms. Angular herself, led off today to a packed house. Again it was really cool to see in person someone I have been reading about in blogs and hearing about in podcasts for a while. Angular 2 is meant to be smaller, lighter and faster than Angular 1, and appeared to be in the demos (hopefully in real life as well). Works with a variety of languages- ES5 and 6 (of interest to me because they are similar to C#), TypeScript, and Dart (which I had never heard of).Hack Proofing Your Modern Web Applications
Another great session that will be useful immediately. Not going to say too much until after we, uh, check on some things at work ;) The presenter, Adam Tuliper, went over the common attacks, SQL Injection, Cross-Site Scripting, etc. and how the bad guys are using them in today's mobile-enabled world.
General Session: Coding, Composition, and Combinatorics
Billy Hollis is another speaker I was familiar with through podcast interviews, Channel 9, and PluralSight. He's another fantastic presenter that was a real treat to see in person.He basically challenged all the coders in the room (basically everyone) to think more about design and solving problems in a logical way rather than "throwing code" at problems. IE. Compose screens that "just work" (from user's job point of view). Easier said than done for folks like me. ;)AngularJS & ASP.NET MVC Playing Nice
Another excellent presentation by Miguel Castro- how to use Angular 1 and MVC in the same app. Essentially each MVC "page" contains an Angular "s.p.a.". I can't think of any business cases where we would need to do this at work, but it's nice to know it's possible, albeit messy- especially the routing. If I remember correctly, by default MVC routing will take precedence over Angular routing.Angular 2 Forms and Validation
Deborah Kurata presented. She along with John Papa seem to be the foremost authorities in Angular 2. The templating story looks really cool, but she made it pretty clear that it's not written in stone yet. Unfortunately I won't have time to dig into this anytime soon. Too many other things I need to focus on- XAML, WPF, MVVM, EF6, unit testing, modern design, Dependency Injection...
Acceptance Testing in Visual Studio 2015
Unfortunately this day last session of the day was a disappointment. Should have gone to ES6 session instead. About five minutes of the talk was devoted to unit testing, which was useful. But the rest was very Agile/Scrum-oriented which is not how we do development at work, and tools and services that we don't have with our version of Visual Studio and MS Enterprise License. I spent most of the session catching up on work and email.
Labels:
Angular,
Austin,
C#,
Security,
Visual Studio,
Visual Studio Live!,
WPF
Thursday, May 19, 2016
Visual Studio Live! Austin - Day 2 (Tuesday 5/17/2016)
Another long day crammed with useful and exciting stuff-
Keynote: Visual Studio - Looking Into the Future
Pretty exciting preview of the next version of Visual Studio "15" (different than Visual Studio 2015) and Xamarin. Very exciting mobile story! And most amazing that a big muckety muck at Microsoft did his presentation on a MacBook! Times are a changing.Developer Productivity in Visual Studio 2015
Unfortunately, the first breakout session of the day was a bit of a disappointment. In hindsight I wish I attended the session on ASP.NET Core 1.0 in this time slot. Not a total loss though. There are some things about VS2015 that are very compelling, like Diagnostic Tools. Pretty cool to have real-time information about CPU and memory utilization while in debug mode. Conditional break points and auto-generated unit test (Intellitest) look very interesting as well. Really looking forward to upgrading- my current project uses VS2013.End-to-End Dependency Injection & Writing Testable Software
Lots of great sessions in this time slot and I chose this one. Great choice! Miguel Castro is a fantastic presenter! Highly recommend hearing him speak if you ever get the chance. In spite of his gruff New Jersey demeanor he's actually very friendly and I've had a few enjoyable chats with him between sessions. And of course the topic is of great relevance to me and I took away a lot!My current project at work is the first one that has embraced unit testing in a big way. I won't say we're going it wrong, but we're definitely doing it the hard way! Using Dependency Injection is way easier than manually creating mock model objects for every model object for every testing scenario as we have been doing it. DI is a much better way to go and I have some work to do when I get back to the office. Fortunately there is another session today (Thursday) that focuses on DI.
General Session: JavaScript and the Rise of the New Virtual Machine
Scott Hanselman was the second general session presenter of the day. As a long time listener of his Hanselminutes podcast it was a real treat to see him speak in person. Really inspired to learn ES6! Unfortunately too many other things to learn first.
Big Data and Hadoop with Azure HDInsight
My motivation for attending this session is an application I inherited at work. It's simply a tool that aggregates massive amounts of financial data and makes it available for queries and reports. There are no transactions. The data is only updated once every quarter. And the system is slow as molasses. So it's would be an ideal candidate for conversion to some sort of big data/data warehouse solution.
Hadoop is a big data processing tool and it was neat to learn how it worked. Unfortunately it has a pretty steep learning curve and the solution presented (HDInsight) appears to be a cloud-only solution. We're a completely on-prem shop and will be for the foreseeable future. So I probably won't be able to play in this space anytime soon.
Hadoop is a big data processing tool and it was neat to learn how it worked. Unfortunately it has a pretty steep learning curve and the solution presented (HDInsight) appears to be a cloud-only solution. We're a completely on-prem shop and will be for the foreseeable future. So I probably won't be able to play in this space anytime soon.
Go Mobile with C#, Visual Studio, and Xamarin
Fantastic session! James Montemagno was another fantastic inspirational speaker and gave a great presentation about using Xamarin Forms in VS2015 to develop mobile apps. Live on stage he wrote an app in XAML and C# using the Xamarin Plugin for Visual Studio 2015 and built/deployed it to both a Android and iOS simulators, and ran it successfully. It was even able to access native resources like the camera and GPS. He was even able to set break points in his code and debug on the simulators. Very exciting and inspiring to me that I can build mobile apps with my existing skill set. Totally want to download VS2015 and get my code on!
Wednesday, May 18, 2016
Visual Studio Live! Austin - Day 1 (Monday 5/16/2016)
Haven't blogged in a while because most of the issues and problems we've solved at work lately are already well documented at StackOverflow and elsewhere on the web. And then there's this week. I have lots to talk about because work has been very kind to send me and a coworker to Visual Studio Live! here in Austin!
Monday was all day workshops. We chose Building Modern Mobile Apps with Brent Edwards and Kevin Ford. Fantastic session with a massive amount of great information, but it was a long exhausting day. The workshop format involved taking an example app and building/testing/deploying it in a variety of ways, explaining the details and pros/cons of each:
Monday was all day workshops. We chose Building Modern Mobile Apps with Brent Edwards and Kevin Ford. Fantastic session with a massive amount of great information, but it was a long exhausting day. The workshop format involved taking an example app and building/testing/deploying it in a variety of ways, explaining the details and pros/cons of each:
- Responsive web app
- Native Android - Java, Android SDK, emulator, ADB deploy tool, Gradle, etc.
- Native iOS - XCode, Swift / Objective C, provisioning profiles, etc.
- Apache Cordova
- Xamarin native
- Xamarin Forms
Labels:
Android,
Cordova,
iOS,
Visual Studio,
Visual Studio Live!,
Xamarin
Location:
Austin, TX, USA
Tuesday, April 5, 2016
WPF/MVVM - tracking when an object has changed
The slow path along the WPF/MVVM learning curve continues. Unfortunately it seems to make some things that should be simple very difficult. One of those things is tracking when an object has changed. This is needed to enable /disable save buttons, or ask the user "Are you Sure?" if he or she navigates away from a record with unsaved changes.
I implemented an IsDirty flag to do this. The problem I ran into is that the PropertyChanged event fires when by UserControl is being initialized but AFTER the view model's constructor code finishes. So, the IsDirty flag is always true when the UserControl is first loaded, even though the user has not changed anything.
I had a very hard time figuring it out and was amazed how little information there was about the problem. Surely I'm not the only one that's encountered this. I probably just didn't know the right things to Google. Here's my solution. Feel free to comment if you know a better way.
I implemented an IsDirty flag in my view model. There are plenty of examples of how to do this. Then I added a command to reset the flag to false when the view has finished rendering. In other words, this causes the view model to ignore any PropertyChanged events that fire before the view is rendered.
Simplified version of my View Model class:
// Property that the controls on the view are bound to
private Entity boundData;
public Entity BoundData
{
get
{
return boundData;
}
set
{
boundData = value;
NotifyPropertyChange("BoundData");
}
}
// Command that the view will use to tell the view model when it's finished rendering
public ICommand OnLoadedCommand { get; private set; }
// Constructor
public void MyUserControlViewModel()
{
// Get data from a data service, which in turn queries an Entity Framework ObjectContext
BoundData = myDataService.GetData();
// wire up the PropertyChanged event handler
BoundData.PropertyChanged += BoundData_PropertyChanged;
// wire up the OnLoadedCommand
OnLoadedCommand = new DelegateCommand(OnLoaded);
// Reset the IsDirty flag. But does not do any good because PropertyChanged events
// fire after this code executes, but before the UserControl has rendered.
IsDirty = false;
}
void BoundData_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
IsDirty = true;
}
public void OnLoaded()
{
// Ignore any PropertyChanged events that fire before the UserControl is rendered.
IsDirty = false;
}
// implementation of the IsDirty flag
private bool _isDirty = false;
public bool IsDirty
{
get
{
return _isDirty;
}
set
{
_isDirty = value;
NotifyPropertyChange("IsDirty");
}
}
Here is the command that fires when the view has finished rendering
<UserControl x:Class="MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding Path=OnLoadedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Tuesday, March 22, 2016
Megabus Review
Last week the kids were on spring break so we went to San Antonio for a few days by Megabus. It was our first time on one.
The San Antonio "bus stop" (see below) was convenient for us, about 4 blocks from our hotel on the Riverwalk. There is easy city bus access from there to all the "touristy" stuff like The Zoo, Sea World, Fiesta Texas, The Pearl Brewery Art Museum, etc.
Good
What's not to like about a double-decker bus? The seats were equivalent to economy class on a US airline. We paid extra for the 'premium' seats on the top deck towards the front, which have a little extra leg room, small tables, and electrical outlets. Even paying for 'premium' seats for all four of us both ways the total was about $70. The bus had Wifi, but most streaming services like YouTube, Netflix, and Pandora were blocked.The San Antonio "bus stop" (see below) was convenient for us, about 4 blocks from our hotel on the Riverwalk. There is easy city bus access from there to all the "touristy" stuff like The Zoo, Sea World, Fiesta Texas, The Pearl Brewery Art Museum, etc.
Not So Good
The "bus stops" are actually parking lots. In Austin this wasn't a big deal because it was next to Dobie Mall and therefore access to food and bathrooms. There was also a gate agent-type person and a security guard. However in San Antonio there was nothing but a parking lot in the middle of an industrial area.Overall
We'll probably ride it again the next time we go to San Antonio. The kids liked it and it sure beats driving on I-35 in rush hour and parking downtown.
Labels:
Austin,
Family,
Megabus,
San Antonio,
Spring Break
Thursday, March 10, 2016
Microsoft in the News
I work in a Microsoft-centric shop and some of their recent developments are of great interest:
http://arstechnica.com/information-technology/2016/03/sql-server-for-linux-coming-in-mid-2017/
SQL Server for Linux
The next major version of SQL Server (2016) will be available for Linux. This could have a big impact on licensing costs- Linux is heaps cheaper than Windows Server.http://arstechnica.com/information-technology/2016/03/sql-server-for-linux-coming-in-mid-2017/
Microsoft buying Xamarin
Xamarin is a product that compiles C# code into native iOS and Android. I'm following this acquisition closely and am hoping Microsoft will fold Xamarin into Visual Studio because that will make it feasible for organizations like mine to build iPhone/iPad and Android apps using our current tools and skill sets. Otherwise we would have to set up separate dev environments and learn the languages of each platform (Objective-C, Java, Swift, etc. ), which isn't really an option at my small shop.
https://blogs.microsoft.com/blog/2016/02/24/microsoft-to-acquire-xamarin-and-empower-more-developers-to-build-apps-on-any-device/
It will be interesting to see what Microsoft decides to do with this.
It will be interesting to see what Microsoft decides to do with this.
Labels:
Android,
C#,
iOS,
Linux,
Microsoft,
SQL Server,
Visual Studio,
Xamarin
Wednesday, March 9, 2016
WPF/MVVM - The ObservableCollection strikes back
Currently I am leading a project to rewrite one of my organization’s major internal apps. I got to choose the architecture and decided on WPF/XAML, the MVVM pattern, and Entity Framework 6. All three are new to me and have pretty significant learning curves. Welcome to the new world. Well, new world for me anyway and apparently old world for everyone else since 2009.
Pretty early on I fell into what I now know is a common WPF “trap for new players”. When you display a list box or gridview of items in an ObservableCollection, changes to items within the ObservableCollection don’t fire its INotifyPropertyChanged event. Fortunately this problem is well known and solutions are easy to find. I ended up using this one-http://www.codeproject.com/Articles/660423/ObservableCollection-notification-on-member-change
Unfortunately this only solved half of the problem for me. I’m using Entity Framework in Database First Mode because I have to use an existing SQL Server database. Therefore my ObservableCollections don’t implement INotifyPropertyChanged, even though, after implementing the above solution, the ObservableCollection is listening for it.
After lots of Googling and testing I ended up using PropertyChanged.Fody to fix this. It implements INotifyPropertyChanged at compile time into whatever model objects you specify- http://www.codeproject.com/Tips/853383/Adding-INotifyPropertyChanged-to-Entity-Framework
I hope someone will find this helpful.
Pretty early on I fell into what I now know is a common WPF “trap for new players”. When you display a list box or gridview of items in an ObservableCollection, changes to items within the ObservableCollection don’t fire its INotifyPropertyChanged event. Fortunately this problem is well known and solutions are easy to find. I ended up using this one-http://www.codeproject.com/Articles/660423/ObservableCollection-notification-on-member-change
Unfortunately this only solved half of the problem for me. I’m using Entity Framework in Database First Mode because I have to use an existing SQL Server database. Therefore my ObservableCollections don’t implement INotifyPropertyChanged, even though, after implementing the above solution, the ObservableCollection is listening for it.
After lots of Googling and testing I ended up using PropertyChanged.Fody to fix this. It implements INotifyPropertyChanged at compile time into whatever model objects you specify- http://www.codeproject.com/Tips/853383/Adding-INotifyPropertyChanged-to-Entity-Framework
I hope someone will find this helpful.
Tuesday, March 8, 2016
Hello world!
Hi everyone! Thanks for reading my first blog post ever. I guess I’ll start off with a little about me and why I’ve started doing this.
I’m developer and DBA at a small IT shop in Austin Texas. For about 10 years now I’ve been working with the Microsoft .Net stack- currently C#, WPF/XAML, T-SQL, LINQ, Razor, Javascript/J-Query, HTML, etc. I’m also a husband, father, Cub Scout den leader, amateur endurance athlete (road-biking and triathlon), and entry-level yogi. And I try to get a little sleep every now and then.
So why blog? Will I have enough to say? And will anyone care? Fortunately in the past year my organization has been making great leaps forward technology-wise. I’m learning a lot- often the hard way. Other people’s blogs have been very helpful getting me over the learning curve. So I would like to try to give back. And Scott Hanselman’s “Get Involved” video on Pluralsight- https://app.pluralsight.com/library/courses/get-involved inspired me to take the plunge. So here we go. Hope you enjoy it!
I’m developer and DBA at a small IT shop in Austin Texas. For about 10 years now I’ve been working with the Microsoft .Net stack- currently C#, WPF/XAML, T-SQL, LINQ, Razor, Javascript/J-Query, HTML, etc. I’m also a husband, father, Cub Scout den leader, amateur endurance athlete (road-biking and triathlon), and entry-level yogi. And I try to get a little sleep every now and then.
So why blog? Will I have enough to say? And will anyone care? Fortunately in the past year my organization has been making great leaps forward technology-wise. I’m learning a lot- often the hard way. Other people’s blogs have been very helpful getting me over the learning curve. So I would like to try to give back. And Scott Hanselman’s “Get Involved” video on Pluralsight- https://app.pluralsight.com/library/courses/get-involved inspired me to take the plunge. So here we go. Hope you enjoy it!
Subscribe to:
Posts (Atom)
