I have an ActiveX control, which is an XML Editor (XMetal XMax). I have included this as a COM component (WindowsFormsHost) in my WPF project. The editor's content model, such as XML Schema, CSS, XML elements, XML attributes, etc., are pre-configured by an XMetal Developer utility, and assigned to the XML editor in the WPF implementation as a single file with the suffix ".xac".
Step 1 - Works:
When I add the XML Editor to a grid (this.grid1.Children.Add (host)), everything works great. The XML Editor and all XML content is displayed.
Now I go one step further and have integrated XCeed AvalonDock as a layout base.
Step 2 - Does Not Work:
The prerequisites are the same as in step 1. If I assign the XML Editor to the "x: Name" property of an "xcad: LayoutDocument", I get an error message.
Although the symbol of the XML Editor is visible in the "xcad: LayoutDocument", the XML basic configuration .xac file will not be loaded. An error message appears.
As I said, when assigning to a Grid.Row everything works fine.
I have tried a lot, but unfortunately without success. Can someone give me some help please. Many Thanks.
public partial class MainWindow : Window
{
public AxXMetaLControlLib.AxXMetaLControl axXmax;
System.Windows.Forms.Integration.WindowsFormsHost host;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Create the interop host control.
host = new System.Windows.Forms.Integration.WindowsFormsHost();
// Create the ActiveX control.
axXmax = new AxXMetaLControlLib.AxXMetaLControl();
// Assign the ActiveX control as the host control's child.
host.Child = axXmax;
// Add the interop host control to the Grid
// control's collection of child controls.
this.XMaxControl.Content = host;
//this.grid1.Children.Add(host);
// Load an XML File into XMAX
axXmax.LoadFromFile("C:/Users/Administrator/Desktop/VS_XMax_PiMod/XMax_PiMod_01/instance1.xml", "C:/001_Mein/001_CMS_Projekt/01_Mein_Projekt/01_Finale/wCMS_02/XMax_Dateien/pi-mod.xac", XMetaLControlLib.SQDocViewType.sqViewTagsOn);
}
}
<Grid x:Name="grid1">
<StackPanel>
<xcad:DockingManager>
<xcad:LayoutRoot>
<xcad:LayoutPanel Orientation="Vertical">
<xcad:LayoutPanel Orientation="Horizontal"
DockHeight="*">
<xcad:LayoutAnchorablePaneGroup DockWidth="150"
Orientation="Vertical">
<xcad:LayoutAnchorablePane DockHeight="100">
<xcad:LayoutAnchorable x:Name="myXmax" Title="Tool 1">
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
<xcad:LayoutAnchorablePane DockHeight="70">
<xcad:LayoutAnchorable Title="Tool 2">
<TextBox />
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
</xcad:LayoutAnchorablePaneGroup>
<xcad:LayoutDocumentPaneGroup>
<xcad:LayoutDocumentPane>
<xcad:LayoutDocument x:Name="XMaxControl" Title="Doc1">
</xcad:LayoutDocument>
<xcad:LayoutDocument Title="Doc2">
<TextBox />
</xcad:LayoutDocument>
</xcad:LayoutDocumentPane>
</xcad:LayoutDocumentPaneGroup>
<xcad:LayoutAnchorablePaneGroup DockWidth="250"
Orientation="Vertical">
<xcad:LayoutAnchorablePane>
<xcad:LayoutAnchorable Title="Attribute Manager">
<xctk:PropertyGrid x:Name="propertyGrid" SelectedObject="{Binding}" >
</xctk:PropertyGrid>
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
</xcad:LayoutAnchorablePaneGroup>
</xcad:LayoutPanel>
<xcad:LayoutAnchorablePaneGroup DockHeight="150">
<xcad:LayoutAnchorablePane>
<xcad:LayoutAnchorable x:Name="prop" Title="Tool 4">
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
</xcad:LayoutAnchorablePaneGroup>
</xcad:LayoutPanel>
</xcad:LayoutRoot>
</xcad:DockingManager>
</StackPanel>
</Grid>
Related
I am having trouble with custom fonts in my Windows Phone 8.1 MVVM app.
I am using FontAwesome icons. I have included the FontAwesome font file in my project. When I set a static control such as this, it works perfectly;
<TextBlock x:Name="txtTest" Grid.Row="3" Text="" Foreground="Black" FontSize="20" FontFamily="/Assets/Fonts/FontAwesome.ttf#FontAwesome"/>
However, what I need is for this to work dynamically. I have a Hub control on the main page of the app, with ListViews in each Hub section. These are bound to a collection of custom objects, populated from an API response. When creating the collection of objects, the code looks for a marker in the response and dynamically sets the FontAwesome icon depending on the marker.
Hub Section code:
<HubSection x:Uid="hubApproved" Header="Approved"
DataContext="{Binding MyObjects.Approved}"
d:DataContext="{Binding MyObjects.Approved}"
HeaderTemplate="{ThemeResource HubSectionHeaderTemplate}" >
<DataTemplate>
<ListView
ItemsSource="{Binding}"
ItemTemplate="{ThemeResource ApprovedTemplate}"
IsItemClickEnabled="True"
ItemClick="ListView_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
</ListView>
</DataTemplate>
</HubSection>
And here is the Approved Template which binds to this:
<DataTemplate x:Key="ApprovedTemplate">
<StackPanel Margin="0,0,0,19" Background="{x:Null}" >
<TextBlock FontFamily="/Assets/Fonts/FontAwesome.ttf#FontAwesome" Text="{Binding Icon}" Foreground="Black" />
<TextBlock Text="{Binding SupplierName}" Style="{ThemeResource ListViewItemTripNameTextBlockStyle}" />
<TextBlock Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" Text="{Binding StartDate}"></TextBlock>
</StackPanel>
</DataTemplate>
The Template contains a TextBlock which binds to the Icon property of my object. This is supposed to then display the appropriate FontAwesome icon, but instead just displays the unicode of the icon:
I have tried defining the font family of the Hub control from the code behind in the view, but it has no effect:
Hub.FontFamily = new FontFamily("ms-appx:///Assets/Fonts/FontAwesome.otf#FontAwesome");
Any ideas on how to dynamically get these icons to display...? Thanks
You should be able to do it like this:
FontFamily fontFam = new FontFamily("ms-appx:///Assets/Fonts/FontAwesome.otf#FontAwesome");
and set FontFamily like this:
Hub.FontFamily = fontFam
I solved this with a workaround. The icons in my ListView will only ever be 1 of 5 possible icons. So instead of setting the unicode, I created 5 different textbox objects in the template definition, one for each icon. The unicode is static, so the dynamic aspect is instead the Visibility of each object. I created corresponding XAML Visibility properties on the custom object. After this, the style object is bound to its Visibility property, like so:
<!--Generic (shopping cart icon)-->
<TextBlock FontFamily="/Assets/Fonts/FontAwesome.otf#FontAwesome" Grid.Column="0" Text="" Style="{ThemeResource ListViewItemTripNameTextBlockStyle}"
VerticalAlignment="Center" Visibility="{Binding VisGeneric}" />
Then when I create the object collection from the API response, I set the appropriate visibility property to be Visible, according the the marker in the response.
I'd like a slightly more elegant solution than this, but essentially it works...
Created a Hub App in WP8.1, I have a ListView that i need to modify the selection mode when the appbar button is pressed. I cannot access the x:Name given to the listview in the .cs code behind. I have had this working on a normal page, just not working in the Hub App.
I cant access the x:Name="WeatherListView" in the c# to change the selectionmode
<Grid x:Name="LayoutRoot">
<!--TODO: Content should be placed within the following grid-->
<Grid Grid.Row="0" x:Name="ContentRoot" Margin="19,9.5,19,0">
<Hub x:Name="AHubView" x:Uid="Hub" Header="A View" SectionsInViewChanged="AHubVieww_SectionsInViewChanged" >
<!--Background="{ThemeResource HubBackgroundImageBrush}"-->
<HubSection Name="WeatherHub" x:Uid="WeatherHub" Header="Weather Hub" DataContext="{Binding HubData}"
d:DataContext="{Binding}"
>
<DataTemplate >
<ListView
x:Name="WeatherListView"
SelectionMode="Multiple"
ItemClick="WeatherListView_OnItemClick"
ItemsSource="{Binding DataVal}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
private void WeatherRemoveAppBarButton_OnClick(object sender, RoutedEventArgs e)
{
SetDefaultWeatherButton(false);
SetWeatherDeleteButton(true);
}
Can't access <Controls> like that if it is part of a <DataTemplate>, you need to browse the VisualTree and extract it out or Databind the SelectionMode to a property in your ViewModel. And changing this Property should change the SelectionMode if done correctly.
VisualTree Exaction Example, I recommend using the Databinding Method however.
I have LayoutDocumentPane in my xaml named MainWindowPane. I am programmtically adding Tabs in the Pane using the below code.
MyViewer viewer = new MyViewer();
LayoutDocument tempTabItem = new LayoutDocument();
tempTabItem.Closed += onTabItemClosed;
tempTabItem.Content = viewer;
MainWindowPane.Children.Add(tempTabItem);
MainDockManager.ActiveContent = 0;
Now Tabs are successfully added in the window , but when I click on any other tab , my app crashes and when I see the stack trace , it says it crashed on onModelChanged() Function.
Please help me out regarding this.
After lot of debugging found a solution for my question..
There was a threading issue as the layout inside my tabs was intitalized using a background worker, so it was not completely done while i was switching.
So now waited for the background worker to complete and then added the new Tab.
Try using this as a guide to what's not working with your code. I think you might be using the LayoutDocumentPane family instead of LayoutAnchorablePane.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock"
xmlns:s="clr-namespace:System;assembly=mscorlib">
<xcad:DockingManager>
<xcad:LayoutRoot>
<xcad:LayoutPanel Orientation="Horizontal">
<xcad:LayoutAnchorablePaneGroup DockWidth="125">
<xcad:LayoutAnchorablePane>
<xcad:LayoutAnchorable ContentId="alarms" Title="Alarms">
<ListBox Margin="-1,0,1,0">
<s:String>Alarm 1</s:String>
<s:String>Alarm 2</s:String>
<s:String>Alarm 3</s:String>
</ListBox>
</xcad:LayoutAnchorable>
<xcad:LayoutAnchorable ContentId="journal" Title="Journal" >
<RichTextBox>
<FlowDocument>
<Paragraph FontSize="14" FontFamily="Segoe">
This is the content of the Journal Pane.
<LineBreak/>
A
<Bold>RichTextBox</Bold> has been added here
</Paragraph>
</FlowDocument>
</RichTextBox>
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
</xcad:LayoutAnchorablePaneGroup>
</xcad:LayoutPanel>
</xcad:LayoutRoot>
</xcad:DockingManager>
I am trying to create UI from XAML at runtime, with something like
private void Application_Startup (object esender, StartupEventArgs e)
{
this.RootVisual = (UIElement)(XmlReader.Load(e.InitParams["Xaml"])
If I feed it this XAML:
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sdk="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls">
<StackPanel>
<TextBox Width="120" Margin="8" Text="Edit Me" />
<CheckBox Margin="8">Normal</CheckBox>
<ComboBox Margin="8" Width="120" SelectedIndex="1">
<ComboBoxItem Content="First Normal Item" />
<ComboBoxItem Content="Second Normal Item" />
</ComboBox>
</StackPanel>
</Canvas>
then the check box and list behave as expected, but my TextBox does not respond to typing, it stays with its initial value.
The really weird (to me) part is that if I put a handler for KeyDown on to the RootVisual, and in there display a message box, it works. If I have an empty handler or no handler it doesn't.
Do I need to set up some explicit handling for some events? If so, which ones, and how do I handle them?
Upadate: as suggested, I tried putting the dynamic markup into the MainPage of a new app, like this:
public MainPage()
{
InitializeComponent();
var dynamic = XamlReader.Load(xaml);
this.LayoutRoot.Children.Add(dynamic as UIElement);
}
where xaml is a string literal containing the content as above, and everything else is just how VS2010 wizard left it. That works. But I can't see what the effective difference is.
Update update: that's a red herring; the difference is the environment. It works in VS, but not in the Silverlight ActiveX control that I am using in the real app.
Did you define the root namespace on your root element?
<param name="initParams" value="xaml=<TextBox xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' Text='hi'/>" />
Just a shot in the dark here, but have you tried adding the dynamically created content as the child of a static "MainPage.xaml" Grid instead of as RootVisual?
Check for IsEnabled="True" property in your main XAML file, if it is set to false then controls will not be editable.
I'm trying to implement "Mega Menu" style menus using WPF. To see examples of mega menus in web design, see here.
So far, I've tried creating a similar interface by using TextBlocks as the highest level of the menu, and then using the mouse hover event to display an additional window that appears positioned below the text block. This is cumbersome and inflexible, future changes would require adding/removing TextBlocks dynamically.
I have considered using the WPF Menu control, because I know the styles can be dramatically modified, but I haven't seen any way to produce multi-column layouts with the hierarchical model that the Menu control uses.
Is there a better way to do this? Am I going to have to stick with custom windows and relative positioning? Can someone point me to an example of this that has already been implemented?
Instead of using custom Windows and positioning, you could use a Popup control. Your can use the StaysOpen=false setting to have it close when the user clicks off-screen.
If you can settle for clicking a menu item instead of hovering, the following custom control will work:
[TemplatePart(Name="PART_HoverArea", Type=typeof(FrameworkElement))]
[TemplatePart(Name="PART_Popup", Type=typeof(Popup))]
public class MegaMenuItem : HeaderedContentControl
{
private FrameworkElement hoverArea;
private Popup popup;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// Unhook old template
if (hoverArea != null)
{
hoverArea.PreviewMouseUp -= ShowPopupOnMouseDown;
}
hoverArea = null;
popup = null;
if (Template == null)
return;
// Hook up new template
hoverArea = (FrameworkElement)Template.FindName("PART_HoverArea", this);
popup = (Popup)Template.FindName("PART_Popup", this);
if (hoverArea == null || popup == null)
return;
hoverArea.PreviewMouseUp += ShowPopupOnMouseDown;
}
private void ShowPopupOnMouseDown(object sender, MouseEventArgs e)
{
popup.PlacementTarget = hoverArea;
popup.Placement = PlacementMode.Bottom;
popup.StaysOpen = false;
popup.IsOpen = true;
}
}
You would need a style to display it - something like this. Note the PART_ template part names:
<Style TargetType="WpfApplication14:MegaMenuItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="WpfApplication14:MegaMenuItem">
<Grid>
<Border Name="PART_HoverArea" Background="#fb9c3b" BorderBrush="White" BorderThickness="0,0,1,0">
<ContentPresenter Content="{TemplateBinding Header}" />
</Border>
<Popup
Name="PART_Popup"
PlacementTarget="{Binding ElementName=HoverArea}"
>
<Border MinWidth="100" MaxWidth="400" MinHeight="40" MaxHeight="200" Background="#0d81c3">
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The XAML for your menu would then be:
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<WpfApplication14:MegaMenuItem Header="Parent 1">
<WrapPanel Margin="5">
<TextBlock Text="Put any content you want here" Margin="5" />
<TextBlock Text="Put any content you want here" Margin="5" />
<TextBlock Text="Put any content you want here" Margin="5" />
</WrapPanel>
</WpfApplication14:MegaMenuItem>
<WpfApplication14:MegaMenuItem Header="Parent 2">
<WrapPanel Margin="5">
<TextBlock Text="Put any content you want here" Margin="5" />
<TextBlock Text="Put any content you want here" Margin="5" />
<TextBlock Text="Put any content you want here" Margin="5" />
</WrapPanel>
</WpfApplication14:MegaMenuItem>
</StackPanel>
Making the menu appear on hover is much harder, because of the way Popups steal focus (you can show the menu, but you can't easily hide it if they mouse over another menu). For that a custom window might work better.
You could use a HeaderedItemsControl and swap out the Panel to suit your needs; by default it uses a StackPanel however a WrapPanel may suit you better. The pop out and mouse over behavior do not exist by default and would need to be implemented.
A more robust approach would be to leverage a custom Expander; as it provides the pop out behavior you are after and the linked to walkthrough provides the mouse over behavior.
I wonder if the Ribbon control can be retrofitted to do this? It provides tabs, labels, columns and all that.
Please use this UI design sparingly and make sure that it only opens and closes when the user specifically requests such. It's tremendously annoying when a popup mega-menu appears over a website I'm viewing, and I can't get it to close, except for when I want to click on it and it goes away.
Custom windows and relative position are essentially how the WPF Menu/MenuItem control works... but as you've found, it's non-trivial. Best bet would be to retemplate the Menu/MenuItem controls to meet your need.