Showing posts with label windows forms. Show all posts
Showing posts with label windows forms. Show all posts

Monday, December 31, 2012

ClickOnce Dynamically Loaded assemblies + ninject

ClickOnce deployment of my winforms dev tool was failing to the dba team because Microsoft.Web.Administration wasn't installed. Is this feature required for the tool to be useful? Not at all. Did MEF, and it wasn't helpful at all. How do you get MEF assemblies deployed for the clients to be able to pick them up? Read about Dynamically loaded assemblies via ClickOnce. Ah the magic is happening now.
[SecurityPermission(SecurityAction.Demand, ControlAppDomain = true)]
  class DynamicDownload
  {
    // Maintain a dictionary mapping DLL names to download file groups. This is trivial for this sample, 
    // but will be important in real-world applications where a feature is spread across multiple DLLs, 
    // and you want to download all DLLs for that feature in one shot. 
    Dictionary<String, String> DllMapping = new Dictionary<String, String>();

    public DynamicDownload()
    {
      DllMapping["Domain.WebAdministration"] = "Domain.WebAdministration";
      AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
    }

    System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
      Assembly newAssembly = null;

      if(!ApplicationDeployment.IsNetworkDeployed)
      {
        return null; //this was required to debug locally, otherwise reactive was failing to load
        throw new FileLoadException("Cannot load assemblies dynamically - application is not deployed using ClickOnce");
      }
      var deploy = ApplicationDeployment.CurrentDeployment;

      var nameParts = args.Name.Split(',');
      var dllName = nameParts[0];
      string downloadGroupName = DllMapping[dllName];
      try
      {
        deploy.DownloadFileGroup(downloadGroupName);
      }
      catch (DeploymentException de)
      {
        MessageBox.Show("Downloading file group failed. Group name: " + downloadGroupName + "; DLL name: " + args.Name);
        throw;
      }

        newAssembly = Assembly.LoadFile(Application.StartupPath + @"\" + dllName + ".dll");
      
      return newAssembly;
    }
  }
static void RegisterDynamicAssemblies()
    {
      Kernel.Bind<DynamicDownload>().ToSelf().InSingletonScope(); //this should never run twice
      var dd=Kernel.Get<DynamicDownload>(); 

      Kernel.Bind<Func<string, IAdministerIIS>>().ToMethod(context => s => new IISAdministration(s));
    }
And now that feature is dynamically loaded the first time the feature is attempted to be used.

Monday, September 7, 2009

DataTimePicker databinding vs nullable DateTime

I just came across an interesting problem. You can't bind a nullable dateTime directly to a dateTimePicker. At least not easily. Here's an extension method that handles the heavy lifting.


/// <summary>
/// 
/// </summary>
/// <param name="dtp"></param>
/// <param name="dataSource"></param>
/// <param name="valueMember"></param>
/// <remarks>With help from Dan Hanan at http://blogs.interknowlogy.com/danhanan/archive/2007/01/21/10847.aspx</remarks>
public static void BindNullableValue(this DateTimePicker dateTimePicker, BindingSource dataSource, String valueMember)
{
var binding = new Binding("Value", dataSource, valueMember, true);
//OBJECT PROPERTY --> CONTROL VALUE
binding.Format += new ConvertEventHandler((sender, e) =>
{
Binding b = sender as Binding;
if (b != null)
{
DateTimePicker dtp = (binding.Control as DateTimePicker);
if (dtp != null)
{
if (e.Value == null)
{
dtp.ShowCheckBox = true;
dtp.Checked = false;
 
// have to set e.Value to SOMETHING, since it's coming in as NULL
// if i set to DateTime.Today, and that's DIFFERENT than the control's current
// value, then it triggers a CHANGE to the value, which CHECKS the box (not ok)
// the trick - set e.Value to whatever value the control currently has. 
// This does NOT cause a CHANGE, and the checkbox stays OFF.
 
e.Value = dtp.Value;
 
}
else
{
dtp.ShowCheckBox = true;
dtp.Checked = true;
// leave e.Value unchanged - it's not null, so the DTP is fine with it.
}
 
}
 
}
});
// CONTROL VALUE --> OBJECT PROPERTY
binding.Parse += new ConvertEventHandler((sender, e) => {
// e.value is the formatted value coming from the control. 
// we change it to be the value we want to stuff in the object.
Binding b = sender as Binding;
 
if (b != null)
{
DateTimePicker dtp = (b.Control as DateTimePicker);
if (dtp != null)
{
if (dtp.Checked == false)
{
dtp.ShowCheckBox = true;
dtp.Checked = false;
e.Value = (Nullable<DateTime>) null;
}
else
{
DateTime val = Convert.ToDateTime(e.Value);
e.Value =val;
}
}
}
});
dateTimePicker.DataBindings.Add(binding);
 
}