my problem is that the embedded dlls of MahApps.Metro and MahApps.Metro.IconPacks are not working fine.
Used the Visual Studio debugger to check if they are getting loaded and it worked fine. If it could not load them the program would throw a xaml exception.
But for some reason the ResourceDictionaries which are merged are not working in runtime.
Should look like this
But looks like this
(As you can see the text color is different and it is missing the icon on the right side => does not load the styles.)
It looks like the first picture if both Dll's are provided in the directory of the program.
My App.xaml
<Application x:Class="Launcher.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:Launcher.Class.Converter"
>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/FlatSlider.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro.IconPacks;component/Themes/IconPacks.xaml" />
<ResourceDictionary Source="Controls\ColorBrushes.xaml"/>
<ResourceDictionary Source="Controls\CustomMetroWindow.xaml"/>
<ResourceDictionary Source="Controls\CustomListView.xaml"/>
<ResourceDictionary Source="Controls\NewsStyle.xaml"/>
<ResourceDictionary Source="Controls\TextImageBox.xaml"/>
<ResourceDictionary Source="Controls\GlowMetroButton.xaml"/>
<ResourceDictionary Source="Controls\ToggleSwitchWin10.xaml"/>
<ResourceDictionary Source="Simple Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<converter:InverseBooleanConverter x:Key="InverseBooleanConverter" />
<converter:BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<converter:BooleanToVisibilityCollapsedConverter x:Key="BoolToVisibilityCollapsedConverter" />
<converter:MultiObjectToBooleanConverter x:Key="MultiObjectToBooleanConverter" />
<converter:DownloadProgressToVisibilityConverter x:Key="DownloadProgressToVisibilityConverter" />
<converter:MultiObjectToStatusBarColorConverter x:Key="MultiObjectToStatusBarColorConverter" />
<converter:MultiBooleanConverter x:Key="MultiBooleanConverter" />
<converter:MultiBooleanToVisibilityConverter x:Key="MultiBooleanToVisibilityConverter" />
<converter:OpacityToBooleanConverter x:Key="OpacityToBooleanConverter" />
</ResourceDictionary>
</Application.Resources>
My Program.cs
[STAThread]
public static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
var resourceName = Assembly.GetExecutingAssembly().GetName().Name + ".Dll." + new AssemblyName(args.Name).Name + ".dll";
if (!resourceName.Contains("resources"))
{
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
{
if (stream != null)
{
var assemblyData = new Byte[stream.Length];
stream.Read(assemblyData, 0, assemblyData.Length);
return Assembly.Load(assemblyData);
}
}
}
else
{
Assembly requestedAssembly = args.RequestingAssembly;
AssemblyName requestedAssemblyName = new AssemblyName(args.Name);
while (true)
{
// requesting name in format: %assemblyname%.resources
// rewrite to: %assemblyName%.%assemblyName%.%culture%.resources.dll
//
var baseName = requestedAssemblyName.Name.Substring(0, requestedAssemblyName.Name.Length - ".resources".Length);
var name = string.Format("{0}.Dll.Lang.{1}.{2}.resources.dll", baseName, requestedAssemblyName.CultureInfo.Name, Assembly.GetExecutingAssembly().GetName().Name);
// by default for resources the requestingAssembly will be null
Assembly asm = null;
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
// resources have the same name as their belonging assembly, so find by name
var parentName = requestedAssemblyName.Name.Substring(0, requestedAssemblyName.Name.Length - ".resources".Length);
// I'd love to use linq here, but Cecil starts fucking up when I do (null reference exception on assembly.Write)
// without a Linq query it works fine, though
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var assembly in assemblies)
{
if (assembly.GetName().Name == parentName)
{
asm = assembly;
}
}
if (asm == null)
{
// cannot find assembly from which to load
return null;
}
using (var stream = asm.GetManifestResourceStream(name))
{
if (stream != null)
{
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
return Assembly.Load(bytes);
}
}
// did not find the specific resource yet
// attempt to use the parent culture, this follows the .Net resource fallback system
// e.g. if sub resource de-DE is not found, then .Parent will be "de", if that is not found parent will probably be default resource
var fallback = requestedAssemblyName.CultureInfo.Parent.Name;
if (string.IsNullOrEmpty(fallback))
{
// is empty if no longer a parent
// return null so .Net can load the default resource
return null;
}
var alteredAssemblyName = requestedAssemblyName.FullName;
alteredAssemblyName = alteredAssemblyName.Replace(string.Format("Culture={0}", requestedAssemblyName.CultureInfo.Name), string.Format("Culture={0}", fallback));
requestedAssemblyName = new AssemblyName(alteredAssemblyName);
}
}
return null;
};
App.Main();
}
The control
<TextBox x:Name="Username"
Controls:TextBoxHelper.Watermark="{lex:Loc Key=LoginWindow.YourUsername}" Margin="0,20,0,9"
Text="{Binding Config.AuthUsername}"
IsEnabled="{Binding LoggingIn, Converter={StaticResource InverseBooleanConverter}}" TextAlignment="Justify"
>
<TextBox.Resources>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource MetroTextImageBox}">
<Setter Property="Controls:TextBoxHelper.ButtonTemplate">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Grid Background="{TemplateBinding Background}">
<Rectangle>
<Rectangle.Fill>
<VisualBrush>
<VisualBrush.Visual>
<iconPacks:PackIconModern Kind="User" Foreground="{StaticResource MainIconBrush}" />
</VisualBrush.Visual>
</VisualBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Resources>
</TextBox>
This code works for me: (add all libraries as Embedded Resource and set startup object to this class)
public class Program
{
private static Assembly ExecutingAssembly = Assembly.GetExecutingAssembly();
private static string[] EmbeddedLibraries =
ExecutingAssembly.GetManifestResourceNames().Where(x => x.EndsWith(".dll")).ToArray();
[STAThreadAttribute]
public static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
App.Main();
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
// Get assembly name
var assemblyName = new AssemblyName(args.Name).Name + ".dll";
// Get resource name
var resourceName = EmbeddedLibraries.FirstOrDefault(x => x.EndsWith(assemblyName));
if (resourceName == null)
{
return null;
}
// Load assembly from resource
using (var stream = ExecutingAssembly.GetManifestResourceStream(resourceName))
{
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
return Assembly.Load(bytes);
}
}
}
The project file portion was cut off previous answer.
Add this to project file
<!--Then add this is project file.-->
<Target Name="EmbedReferencedAssemblies" AfterTargets="ResolveAssemblyReferences">
<ItemGroup>
<!-- get list of assemblies marked as CopyToLocal -->
<AssembliesToEmbed Include="#(ReferenceCopyLocalPaths)" Condition="'%(Extension)' == '.dll'" />
<!-- add these assemblies to the list of embedded resources -->
<EmbeddedResource Include="#(AssembliesToEmbed)">
<LogicalName>%(AssembliesToEmbed.DestinationSubDirectory)%(AssembliesToEmbed.Filename)%(AssembliesToEmbed.Extension)</LogicalName>
</EmbeddedResource>
</ItemGroup>
<Message Importance="high" Text="Embedding: #(AssembliesToEmbed->'%(DestinationSubDirectory)%(Filename)%(Extension)', ', ')" />
</Target>
<!-- no need to copy the assemblies locally anymore -->
<Target Name="_CopyFilesMarkedCopyLocal" />
I had the same issue you described and came across fix that resolves the issue.
public partial class App : Application {
public App() {
AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
}
private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args) {
var executingAssembly = Assembly.GetExecutingAssembly();
var assemblyName = new AssemblyName(args.Name);
var path = assemblyName.Name + ".dll";
if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) {
path = String.Format(#"{0}\{1}", assemblyName.CultureInfo, path);
}
using (var stream = executingAssembly.GetManifestResourceStream(path)) {
if (stream == null)
return null;
var assemblyRawBytes = new byte[stream.Length];
stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
return Assembly.Load(assemblyRawBytes);
}
}
}
%(AssembliesToEmbed.DestinationSubDirectory)%(AssembliesToEmbed.Filename)%(AssembliesToEmbed.Extension)
'%(DestinationSubDirectory)%(Filename)%(Extension)',
', ')" />
I have got an object in App.xaml.cs as you can see here
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace Test_Project
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//Startup
Window main = new MainWindow();
main.Show();
}
}
/// <summary>
/// Global values for use during application runtime
/// </summary>
public class runtimeObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
....
I'm trying to create an instance of the object for use for the duration my application is running. I'm creating this instance in the XAML in App.xaml
<Application x:Class="Test_Project.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Test_Project">
<Application.Resources>
<local:runtimeObject x:Key="runtimeVariables" />
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
I'm getting the error saying that my class doesn't exist in the namespace. However the xmlns:local does reference the namespace which contains the object, any ideas ?
Woops, the <local:runtimeObject x:Key="runtimeVariables" /> had to go in the <ResourceDictionary> and then I had to rebuild the solution.
I am trying to implement log4net in a helper project (AC.Helpers), and when it runs the configuration, I get the following error in the Output window -
log4net:ERROR Failed to find configuration section 'log4net' in the application's .config file. Check your .config file for the and elements. The configuration section should look like:
LoggerBase.cs -
public abstract class LoggerBase
{
#region Member Variables
/// <summary>
/// Member variable to hold the <see cref="ILog"/> instance.
/// </summary>
private readonly log4net.ILog logger = null;
#endregion
#region Properties
/// <summary>
/// Abstract property which must be overridden by the derived classes.
/// The logger prefix is used to create the logger instance.
/// </summary>
protected abstract System.Type LogPrefix
{
get;
}
#endregion
#region Constructors
private static bool isConfigured = false;
/// <summary>
/// Constructor of the class.
/// </summary>
public LoggerBase()
{
// initiate logging class
if (!isConfigured)
{
log4net.Config.XmlConfigurator.Configure();
isConfigured = true;
}
logger = log4net.LogManager.GetLogger(this.LogPrefix);
}
#endregion
App.config -
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="Console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level: %message%newline" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="Console" />
</root>
</log4net>
</configuration>
Any ideas why I am getting this? Other posts suggest moving the log4net config to its own file and use the following in AssemblyInfo.cs (tried, without success)
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.config", Watch = true)]
I have been learning MVVM / WPF and have gone through the tutorial here.
I have created a working application using this methodology but now, on a new project, I cannot get the Dependency Injection to work.
When I run this project I get an empty MainWindow without the CompanyView injected. I have double and tripled checked everything between the project that works and this one that doesn't and cannot find the reason for CompanyView not being injected. I have also tried cleaning the solution and restarting VS to no avail. Hopefully someone can see what I am missing.
I have the following file:
App.xaml.cs (using base.OnStartup() instead of StartupUri in App.xaml)
namespace SidekickAdmin
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow window = new MainWindow();
var viewModel = new MainWindowViewModel();
window.DataContext = viewModel;
window.Show();
}
}
}
MainWindowViewModel.cs
namespace SidekickAdmin.ViewModel
{
class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel()
{
CompanyViewModel companyViewModel = new CompanyViewModel(_repository);
this.ViewModels.Add(companyViewModel);
}
ObservableCollection<ViewModelBase> _viewModels;
ObservableCollection<ViewModelBase> ViewModels
{
get
{
if (_viewModels == null)
{
_viewModels = new ObservableCollection<ViewModelBase>();
}
return _viewModels;
}
}
}
}
MainWindowView.xaml
<Window x:Class="SidekickAdmin.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:SidekickAdmin.ViewModel"
xmlns:vw="clr-namespace:SidekickAdmin.View"
Title="Sidekick Admin" SizeToContent="WidthAndHeight">
<!-- Typically done in a resources dictionary -->
<Window.Resources>
<ResourceDictionary Source="MainWindowResources.xaml" />
</Window.Resources>
<StackPanel>
<ItemsControl ItemsSource="{Binding ViewModel}" Margin="3" />
</StackPanel>
</Window>
MainWindowResources.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:SidekickAdmin.ViewModel"
xmlns:vw="clr-namespace:SidekickAdmin.View">
<DataTemplate DataType="{x:Type vm:CompanyViewModel}">
<vw:CompanyView />
</DataTemplate>
</ResourceDictionary>
CompanyViewModel.cs (not really used yet as I am still trying to just get the view to appear)
namespace SidekickAdmin.ViewModel
{
class CompanyViewModel : ViewModelBase
{
readonly GenericRepository _repository;
#region Getters & Setters
public ObservableCollection<Company> AllCompanies
{
get;
private set;
}
#endregion
#region Constructors
public CompanyViewModel(GenericRepository repository)
{
if (repository == null)
{
throw new ArgumentNullException("repository");
}
_repository = repository;
this.AllCompanies = new ObservableCollection<Company>(_repository.GetAll<Company>());
}
#endregion
protected override void OnDispose()
{
this.AllCompanies.Clear();
}
}
}
CompanyView.xaml
<UserControl x:Class="SidekickAdmin.View.CompanyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Height="300" Width="300">
<StackPanel>
<TextBlock>You say Hello</TextBlock>
<TextBlock>And I say Goodbye</TextBlock>
<TextBlock>Hello, Hello</TextBlock>
</StackPanel>
</UserControl>
Lester's comment is right... you are binding to a ViewModel property which does not exist - MainWindowViewModel has a ViewModels property though. The s is important
Besides what #Robert Levy has wrote, the error you are making is that your ViewModels property is private, make it public and it should work fine.
#RobertLevy and #dmusial are correct. You need to make your reference to ViewModels in your XAML plural, to match the property name in your C# code. Also, the property should be public, so the View can see it.
Hi I try use Windosor Castle with Caliburn Micro. Until now I use only MEF.
I founf this Castle Boostraper : https://gist.github.com/1127914
I added this calls to my project and modified App.xaml file:
<Application x:Class="Chroma_Configer.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Bootstraper="clr-namespace:Chroma_Configer.Bootstraper">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<Bootstraper:CastleBootstrapper x:Key="bootstrapper" />
<Style x:Key="MainView_FontBaseStyle" TargetType="{x:Type Control}">
<Setter Property="FontFamily" Value="Arial"/>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
I create ShellView (WPF) and ShellViewModel:
public interface IShellViewModel
{
}
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive,
IShellViewModel
{
}
When I run I get this error:
{"No component for supporting the service Chroma_Configer.ViewModels.IShellViewModel was found"}
I am beginer in Windsor Castle I know that he work something like this:
var container = new WindsorContainer();
container.AddComponent("JsonUtil", typeof(IShellViewModel), typeof(ShellViewModel));
var shell = container.Resolve<IShellViewModel>();
In MEF I user attribute [Export] and [Import]. Can me anybody hel me with this issue?
Another question is that I have some tool class:
public interface ITooll{}
public class Tool:ITool{}
and I would like import this in ShellViewModel class.
How can I do it with with CastleBoostraper?
You need to register your view models and views in the container. The older Windsor version worked based on attributes, but on latest version you can do this with the fluent API or even bulk register based on some convention:
public class Bootstrapper : Bootstrapper<IShellViewModel>
{
protected override IServiceLocator CreateContainer()
{
_container = new WindsorContainer();
var adapter = new WindsorAdapter(_container);
_container.Register(Component.For<ITool>().ImplementedBy<Tool>().LifeStyle.Transient);
return adapter;
}
}
You can also create Installers that will register types in the container so your Bootstrapper code will not end up with a lot of registration code:
public class ShellRegistration : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<ITool>().ImplementedBy<Tool>().LifeStyle.Transient);
//Register other types
}
}
And call it in the bootstrapper:
public class Bootstrapper : Bootstrapper<IShellViewModel>
{
protected override IServiceLocator CreateContainer()
{
_container = new WindsorContainer();
var adapter = new WindsorAdapter(_container);
_container.Install(FromAssembly.This());
return adapter;
}
}
Check the Silverlight sample application I have created to find out how to work with Castle Windsor.
You can get instances of your dependencies using Constructor Injection or Property Injection something inline with this:
public class ShellViewModel
{
public ShellViewModel(IMyDependency dependency)
{
//you'll get an instance of the class implementing IMyDependency
//Logger property will be injected after construction
}
public ILog Logger
{
get; set;
}
}