Metro XAML custom control cannot be accessed from code behind - c#

Trying to use the solution to this question gives me a weird problem. (Replicated here for convenience)
This is a solution for an issue with ListView swallowing the right-click event and preventing the AppBar from opening - A class which inherits ListView and overrides the OnRightTapped event of ListViewItem:
public class MyListView : ListView
{
protected override DependencyObject GetContainerForItemOverride()
{
return new MyListViewItem();
}
}
public class MyListViewItem : ListViewItem
{
protected override void OnRightTapped(Windows.UI.Xaml.Input.RightTappedRoutedEventArgs e)
{
base.OnRightTapped(e);
e.Handled = false; // Stop 'swallowing' the event
}
}
<CustomControls:MyListView
x:Name="ItemsList"
...
SelectionMode="Single"
RightTapped="MyListView_RightTapped">
</CustomControls:MyListView>
I have implemented a custom control as specified, in a new namespace called CustomControls, exactly as described. I've added that namespace to MainPage.xaml
xmlns:CustomControls="using:CustomControls"
When I then try and reference 'ItemsList' in code behind, I get a compile error
The name 'ItemsList' does not exist in the current context
I've tried building, rebuilding, cleaning the solution, closing and reopening the solution, putting the classes under the main project namespace, all to no avail.
To summarise, MainPage.cs cannot see a Custom Control on MainPage.xaml
UPDATE 2: Reworded the question to remove irrelevant issues. I've also changed the title to reflect the real issue.

I was using Name but should have been using x:Name. Apparently custom controls and user controls need to use x:Name rather than Name to be seen in code behind.
More info on the difference here:
In WPF, what are the differences between the x:Name and Name attributes?

Related

WPF ResourceDictionary x:Class Function Not Firing

I am currently trying to add functionality to a ResourceDictionary, by declaring it's x:Class and linking an On Click event to a function within said class. Here is an example:
Where I link the x:Class
Where I link an x:Class function to an On Click event:
And the source for my x:Class:
using System;
using System.Windows;
namespace VoidwalkerEngine.Editor.Resources.Themes.Styles
{
public partial class VoidwalkerCellBrowserTreeView : ResourceDictionary
{
public VoidwalkerCellBrowserTreeView()
{
InitializeComponent();
}
private void BaseTreeView_NewFolder_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("Test"); // This should be fired when I click on "New Folder"
}
}
}
A picture of the menu item just before I click it:
After I click the menu item, it should print "Test" to the console. However, nothing happens. Clearly, I must be doing something wrong. I also found a similar question to mine located here: Control event not firing from class linked to resource dictionary wpf
And their suggestion was to add an extra line to the .csproj file, which I did:
However, this still is not working. Obviously I'm still not linking something correctly, I'm just at a loss of how to proceed from here. Does anyone know how to properly link a ResourceDictionary with it's x:Class? My project is throwing no errors, and Visual Studio even auto-completed the BaseTreeView_NewFolder_Click function into the x:Class file, so I know the source file itself is attached just fine.
EDIT 1:
Here is the full XAML ResourceDictionary: https://pastebin.com/8UepKGTa
EDIT 2:
After testing a few things, I noticed something very peculiar. Apparently, any console command I place in the default constructor will be fired, but no methods will be fired. Here is an image:
I'm seriously at a loss right now. The class IS linking just fine, but for whatever reason, the functions won't link to it.
You don't need to manually add that stuff in csprroj.
It works rather like a window.
You need the class to be referred to in the resource dictionary:
The code file must inherit from resourcedictionary and be a partial class:
namespace MapEditor
{
public partial class TerrainResources : ResourceDictionary
And you need the initializecomponent stuff:
public TerrainResources()
{
InitializeComponent();
}
The class properties build action should be compile compile
And of course the resource dictionary must be build action page.
Looking at your code, at first glance it looks like it ought to work.
You have quite a long namespace.
VS doesn't get on well with deep folder structures and very long namespaces.
Where is your menuitem?
I'm using my code there for a loaded event, and that's used from datatemplates inside that resource dictionary:
<DataTemplate DataType="{x:Type local:SwampVM}">
<Polygon Points="{Binding Points}"
Fill="YellowGreen"
local:TerrainProp.TerrainCanvas="{Binding RelativeSource={RelativeSource AncestorType={x:Type Canvas}}}"
FrameworkElement.Loaded="Terrain_Loaded"
Your contextmenu would have to be a resource in the resource dictionary to work with that event.

Moving a template to a resource dictionary, when said template contains code behind reference

I'm creating a WPF application (Visual Studio 2010, C#, MVVM) in which there is a ListBox. I also have a template for the ListBox item, and the template is the source of the issue.
The template is getting pretty big and I want to move it to a resource dictionary. What's stopping me is that this line exists within it:
PreviewMouseRightButtonDown="OnContainingListMouseRightButtonDown"
The method which is run (on a right click event) makes sure the SelectedItem of the ListBox is the same as the one I'm right clicking on: that is to say, it sets the SelectedItem of the ListBox to the one that I right click on.
Obviously if I move the template, this part won't work anymore, but the template is getting rather large.
Is there a way around this?
Edit: I should have mentioned that I reference the items (such as the ListBox by its name) in the code behind as it stands. If I create a new code behind for the resource dictionary, I will no longer have access to those things.
For example, your resource dictionary file name is ListBoxStyle.xaml. You should also create a C# file with name ListBoxStyle.xaml.cs. In your resource dictionary file you should add the following line:
<ResourceDictionary x:Class="CodeBehindNamespace.ListBoxStyle" ...>
It's the reference to your code behind. Your ListBoxStyle.xaml.cs content should be the following:
namespace CodeBehindNamespace
{
public partial class ListBoxStyle : ResourceDictionary
{
public WindowStyle()
{
InitializeComponent();
}
private void OnContainingListMouseRightButtonDown(object sender, RoutedEventArgs e)
{ ... }
}
}

Xaml Parsing Failed when subclassing ListView/GridView/ListBox

I am subclassing ListView in a Windows Universal App Project. I create a new UserControl in Visual Studio 2015 RC and then change the UserControl type to ListView in both XAML and codebehind.
When I insert the control and run the application I get a 'Xaml Parsing Failed' exception without any further information.
Upon researching I came across the issue where the project name contains a dot, but my project name does not contain such characters.
Any Idea how to research this further?
EDIT: I also tried subclassing ListView, GridView, ListBox and Itemscontrol. Itemscontrol does not generate the error but all others do.
EDIT 2:
Created a new Universal App Project in VS2015 RC
Add -> UserControl
Changed Base Class into:
public sealed partial class ListViewEx : ListView
{
public ListViewEx()
{
this.InitializeComponent();
}
}
Changed XAML UserControl tag into ListView
The answer from MSDN forums: use themed control (custom control) for this case.
However, this approach works in WPF, it surprises me.

RibbonGroup causes its children lose their DataContext

I am developing a WPF project and right now I am working on the Ribbon area.
Inside of the Ribbon I have some controls such as RibbonComboBox, RibbonTextBox, etc.
I have several RibbonTab in my Ribbon so I set one view model for each RibbonTab as following:
<rb:Ribbon Name="Ribbon">
<rb:RibbonTab Header="Tab One" Name="tab1">
<rb:RibbonTab.DataContext>
<vm:TabOneViewModel />
</rb:RibbonTab.DataContext>
So, each control within those tabs inherits their respective view model.
When I run the application everything works as expected. The problem starts when I resize the container window to a very small size, after doing this: Every control loses their bindings since their DataContext is replaced by an object called DisconnectedItem.
I have done some research and found that this is due to the controls stop being part of the visual tree and for that reason the binding engine sets their DataContext to DisconnectedItem.
What can I do to prevent my controls from losing their DataContext?
EDIT:
I just found that the main problem comes from the RibbonGroup control which after collapsing causes its visual children lose their DataContext.
I usually add DataContext="{Binding Mode=OneTime}" line for all ribbon controls as a workaround, which fixes the issue completely. You won't be able to change DataContext more than once though.
I just found a workaround for the RibbonGroup control issue here
The solution I took is creating a new control which inherits from RibbonGroup control.
public class MyRibbonGroup : RibbonGroup
{
public MyRibbonGroup()
: base()
{
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
// Force the bindings to be restored after
// the ribbon group collapsed or expanded to a menu button.
if (e.Property == RibbonGroup.IsCollapsedProperty)
{
object objDataContext = this.DataContext;
this.DataContext = null;
this.DataContext = objDataContext;
}
}
}

C# Enhanced Listbox - remembers additional attributes after postback

I'm in a situation where I need a listbox to remember after postback the attributes I've added to a number of the listitems in it. I found this solution online which appears to solve the issue but am not sure how to implement it.
List box solution
He says he wrote a class that inherits from Listbox which is fine, I've done that and have called it EnhancedListBox but how do I then apply that to the Listbox I'm using on the page?
I can't just substitute
<asp:ListBox >
with
<asp:EnhancedListBox>
but how else do I let the page know I want to use my inherited code?
Thanks.
SaveViewState and LoadViewState are virutal methods that you can override. What you want to try is creating "your own" ListBox:
class EnhancedListBox : ListBox
{
protected override object SaveViewState()
{
// code here from the tutorial
}
protected override void LoadViewState(object savedState)
{
// code here from the tutorial
}
}
This is also called "Creating a custom control", it's very common to do it this way and it gives you great flexibility.
you need to create a custom control for this
check this out http://msdn.microsoft.com/en-us/library/ms366537.aspx for the startup.

Categories

Resources