- Details
- Written by: Stanko Milosev
- Category: C#
- Hits: 9097
Let's say we want to create xml like this:
<?xml version="1.0" encoding="utf-8"?>
<project>
<menu bg_img="">
<mnu_item txt="Menu item 1" anotherAttribute="another attribute 1">
<sub_item txt="Sub item 1" articleId="1" />
</mnu_item>
<mnu_item txt="Menu item 2" anotherAttribute="another attribute 2">
<sub_item txt="Sub item 2" articleId="2" />
</mnu_item>
</menu>
</project>
Serialization
First we need model:
[XmlRoot("project")]
public class Project
{
[XmlElement(ElementName = "menu")]
public Menu Menu { get; set; }
}
public class Menu
{
[XmlAttribute("back_image")]
public string backImage {get; set;}
[XmlElement(ElementName = "mnu_item")]
public List<MenuItem> MenuItem { get; set; }
}
public class MenuItem
{
[XmlAttribute("txt")]
public string Txt { get; set; }
[XmlAttribute("anotherAttribute")]
public string AnotherAttribute { get; set; }
[XmlElement("sub_item")]
public SubItem SubItem { get; set; }
}
public class SubItem
{
[XmlAttribute("txt")]
public string Txt { get; set; }
[XmlAttribute("articleId")]
public string ArticleId { get; set; }
}
ViewModel looks like this:
Project serializedProject = new Project();
serializedProject.Menu = new Menu();
serializedProject.Menu.backImage = string.Empty;
MenuItem menuItem = new MenuItem();
menuItem.Txt = "Menu item 1";
menuItem.AnotherAttribute = "another attribute 1";
menuItem.SubItem = new SubItem();
menuItem.SubItem.Txt = "Sub item 1";
menuItem.SubItem.ArticleId = "1";
serializedProject.Menu.MenuItem = new List<MenuItem>();
serializedProject.Menu.MenuItem.Add(menuItem);
menuItem = new MenuItem();
menuItem.Txt = "Menu item 2";
menuItem.AnotherAttribute = "another attribute 2";
menuItem.SubItem = new SubItem();
menuItem.SubItem.Txt = "Sub item 2";
menuItem.SubItem.ArticleId = "2";
serializedProject.Menu.MenuItem.Add(menuItem);
TextWriter txtWriter = new StreamWriter(Path.ChangeExtension(System.Reflection.Assembly.GetEntryAssembly().Location, ".xml"));
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Project), "");
xmlSerializer.Serialize(txtWriter, serializedProject, ns);
txtWriter.Close();
Notice lines:
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
...
xmlSerializer.Serialize(txtWriter, serializedProject, ns);
Without these lines our XML would look like this:
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
Then in model, line, for example:
[XmlAttribute("back_image")]
Means that our attribute will be named as "back_image" in our XML.
Path.ChangeExtension(System.Reflection.Assembly.GetEntryAssembly().Location, ".xml")
With
System.Reflection.Assembly.GetEntryAssembly().Location
We are geting location of our exe file, and with method Path.ChangeExtension we are changing our file extension to XML.
Linq to XML
For linq to XML we don't need model, only XElement, so my code looks like this:
XElement myLinq2XML =
new XElement(
"project",
new XElement(
"menu",
new XAttribute("back_image", string.Empty),
new XElement(
"mnu_item",
new XAttribute("txt", "Linq2XML item 1"),
new XAttribute("anotherAttribute", "another attribute 1"),
new XElement("sub_item",
new XAttribute("txt", "Sub item 1"),
new XAttribute("articleId", "1")
)
),
new XElement(
"mnu_item",
new XAttribute("txt", "Linq2XML item 2"),
new XAttribute("anotherAttribute", "another attribute 2"),
new XElement("sub_item",
new XAttribute("txt", "Sub item 2"),
new XAttribute("articleId", "2")
)
)
)
);
Example project you can download from here.
- Details
- Written by: Stanko Milosev
- Category: C#
- Hits: 5980
Serialization and deserialization. To write this article I was using this web page. First lets serialize the XML. Idea is to create xml like
<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<channels>
<channel>
<urn>test</urn>
</channel>
</channels>
</definitions>
So, first we have to prepare model, and looks like:
public class definitions
{
public List<channel> channels { get; set; }
}
public class channel
{
public string urn { get; set; }
}
Now serialization:
definitions serializeObject = new definitions(); channel channel = new channel(); channel.urn = "test"; serializeObject.channels = new List<channel>(); serializeObject.channels.Add(channel); XmlSerializer xmlSerializer = new XmlSerializer(typeof(definitions)); TextWriter txtWriter = new StreamWriter(@"d:\temp\MyTest.xml"); xmlSerializer.Serialize(txtWriter, serializeObject); txtWriter.Close();
That is all about serialization. Now we well deserialize same XML:
XmlSerializer xmlSerializer = new XmlSerializer(typeof(definitions));
using (FileStream fileStream = File.OpenRead(@"d:\temp\MyTest.xml"))
{
definitions channelDefinitions = (definitions)xmlSerializer.Deserialize(fileStream);
ChannelModels = channelDefinitions.channels;
}
Example project you can download from here.
That's all folks!
- Details
- Written by: Stanko Milosev
- Category: C#
- Hits: 6906
If you have installed Visual Studio 2011, after that changed back to VS 2010, and you are receiving error like:
Error 20: The "EntityHydrate" task failed unexpectedly. System.TypeInitializationException: The type initializer for 'Microsoft.Data.Entity.Design.Model.SchemaManager' threw an exception. ---> System.MissingFieldException: Field not found: 'System.Data.Entity.Design.EntityFrameworkVersions.Version3'. at Microsoft.Data.Entity.Design.Model.SchemaManager..cctor() --- End of inner exception stack trace --- at Microsoft.Data.Entity.Design.Model.SchemaManager.GetSchemaVersion(XNamespace xNamespace) at Microsoft.Data.Tools.Integration.Build.EntityHydrate.Execute() at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute() at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask, Boolean& taskResult) BuildingModule
then do as it is described here, delete files in folder:
C:\Program Files (x86)\MSbuild\4.0\Microsoft.Common.Targets\ImportAfter\Microsoft.Data.Tools.Integration.targets
Note: Use "Program Files" without "(x86)" if you have the 32 bits version of Windows.
and then restart your computer.
- Details
- Written by: Stanko Milosev
- Category: WPF
- Hits: 2019
Introduction
This is a short demonstration of creating custom button in .NET7 (Core) using a new WPF XAML Designer.
Background
Since Visual Studio 2022 the WPF .NET Framework control extensibility model based on .design.dll and Microsoft.Windows.Design.Extensibility is no longer supported. More about it you can read in New WPF XAML Designer for .NET Framework.
Using the code
This example was made using Visual Studio 2022 and there will be one class library (.NET Framework) project and one WPF Custom Control Library needed:
- CustomControlLibrary.WpfCore - WPF Custom Control Library
- CustomControlLibrary.WpfCore.DesignTools - please notice that extension .DesignTools is necessary, and that the project is in .NET Framewok 4.8
- Rebuild and create package from CustomControlLibrary.WpfCore (right mouse button -> pack).
CustomControlLibrary.WpfCore
- Create WPF Custom Control Library and change csproj to look like:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net7.0-windows</TargetFramework> <Nullable>enable</Nullable> <UseWPF>true</UseWPF> </PropertyGroup> <ItemGroup> <PackageReference Include="NuGet.Build.Packaging" Version="0.2.2"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup> <PropertyGroup> <PackageId>CustomControlLibrary.WpfCore</PackageId> <Description>Button example</Description> </PropertyGroup> <ItemGroup> <PackageFile Include="VisualStudioToolsManifest.xml"> <Kind>Tools</Kind> </PackageFile> <PackageFile Include="$(OutputPath)\CustomControlLibrary.WpfCore.DesignTools.dll"> <Kind>Lib</Kind> <TargetPath>Design\CustomControlLibrary.WpfCore.DesignTools.dll</TargetPath> </PackageFile> </ItemGroup> </Project> - Rename CustomControl1 to MyButton, also in Generic.xaml.
- Add VisualStudioToolsManifest.xml.
MyButton
using System.Windows;
using System.Windows.Controls;
namespace CustomControlLibrary.WpfCore
{
public class MyButton : Button
{
public static DependencyProperty RenderActiveProperty;
public bool RenderActive
{
get { return (bool)GetValue(RenderActiveProperty); }
set { SetValue(RenderActiveProperty, value); }
}
static MyButton()
{
RenderActiveProperty = DependencyProperty.Register("RenderActive",
typeof(bool),
typeof(MyButton),
new PropertyMetadata(false));
}
public string Test { get; set; }
}
}
VisualStudioToolsManifest
<FileList>
<File Reference="CustomControlLibrary.WpfCore.dll">
<ToolboxItems UIFramework="WPF" VSCategory="CustomControlLibrary.WpfCore" BlendCategory="CustomControlLibrary.WpfCore">
<Item Type="CustomControlLibrary.WpfCore.MyButton" />
</ToolboxItems>
</File>
</FileList>
CustomControlLibrary.WpfCore.DesignTools
- Install NuGet package Microsoft.VisualStudio.DesignTools.Extensibility:
Install-Package Microsoft.VisualStudio.DesignTools.Extensibility -Version 17.4.33103.184
- Rename Class1 to MyDesignMetadata:
using Microsoft.VisualStudio.DesignTools.Extensibility.Metadata; using System.ComponentModel; [assembly: ProvideMetadata(typeof(XAMLDesignerExtensibilityCore.DesignTools.MyDesignMetadata))] namespace XAMLDesignerExtensibilityCore.DesignTools { public class MyDesignMetadata : IProvideAttributeTable { public AttributeTable AttributeTable { get { AttributeTableBuilder builder = new AttributeTableBuilder(); builder.AddCustomAttributes("CustomControlLibrary.WpfCore.MyButton" , "Test" , new CategoryAttribute("** test **") ); return builder.CreateTable(); } } } } - Set build output pat to something like ..\CustomControlLibrary.WpfCore\bin\Debug\net7.0-windows\ or copy it manually to CustomControlLibrary.WpfCore output folder.