Forums

Difficulties creating a UserControl
Last Post 07 Jul 2016 07:26 PM by ellisonch. 21 Replies.
Printer Friendly
  •  
  •  
  •  
  •  
  •  
Sort:
PrevPrev NextNext
You are not authorized to post a reply.
Page 1 of 212 > >>
Author Messages Resolved
JekevUser is Offline
New Member
New Member
Posts:3


--
01 Sep 2015 01:19 PM
    Hey, first, thanks for the great library, I have been using it a few weeks and it has been really useful.

    Unfortunately I am currently having some difficulties creating a UserControl. I have created a ListBox with an item template that I wish to replicate at multiple points in my UI - but hopefully without having to just copy and paste (and subsequently upkeep) the entirety of the XAML each time. I am not very experienced with WPF, and so I pieced together my solution so far from various random parts of the internet - it might all be complete rubbish...

    To demonstrate the problem I have simplified the it to the basics - and the building process still fails - so I am pretty sure I am doing something systematically wrong with my implementation of a UserControl. The project looks like this:


    I am using the latest (1.8.0.0) version of the library.

    My UI Root:
    <ek:UIRoot x:Class="TestUILibrary.ekRoot1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:ek="clr-namespace:EmptyKeys.UserInterface.Designer;assembly=EmptyKeys.UserInterface.Designer"
            xmlns:local="clr-namespace:TestUILibrary"
            Height="600" Width="600" Background="Transparent">
        <Canvas>
            <local:UserControlTest />
        </Canvas>
    </ek:UIRoot>
    


    and my UserControl
    <UserControl x:Class="TestUILibrary.UserControlTest"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
        <TextBlock Text="MY USER CONTROL" />
    </UserControl>
    


    For both files I have deleted the code behind .cs files (my understanding is that these are irrelevant using the MVVM system, and doing so has served me well so far).

    When I attempt to build this project, I get the following error:


    and the output window complains that:


    Thanks for any help you can provide.

    - Jekev

    Edit: replaced the errors with pictures - they caused the forum to have a bit of a markup hiccup
    Filip DušekUser is Offline
    Advanced Member
    Advanced Member
    Posts:693


    --
    01 Sep 2015 01:49 PM
    Yeah, UI Generator needs to know the type and so you have to keep code-behind class. So don't remove the .cs files for user controls.

    Another issue, which I didn't find better solution, that you have to use assembly in namespace so xmlns:local="clr-namespace:TestUILibrary;assembly=TestUILibrary" and set the build output of library to UI Generator directory.

    JekevUser is Offline
    New Member
    New Member
    Posts:3


    --
    01 Sep 2015 05:08 PM
    Thanks a lot for the response, recreating the UserControl and now keeping the .xaml.cs code-behind class, changing the projects Properties > Build > Output path to "..\EmptyKeysUI\Generator\", and adding the assembly, gives me the following error.

    "The tag 'UserControlTest' does not exist in XML namespace 'clr-namespace:TestUILibrary;assembly=TestUILibrary'. Line 9 Position 10."

    I haven't worked out how to get rid of this error - perhaps you can't - but if you set the post-build to always run, rather than just after a success, you can just ignore this error.

    Additionally, and this might help someone in the future, I have found that you need to compile the UI project before referencing the usercontrol in the ekRoot file, and then add the reference (local:UserControlTest) back in, it seems that otherwise this stops compilation because it doesn't yet exist.

    The next stage of re implementation is to allow binding properties,

     <ek:UIRoot  
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:ek="clr-namespace:EmptyKeys.UserInterface.Designer;assembly=EmptyKeys.UserInterface.Designer" 
             xmlns:local="clr-namespace:TestUILibrary;assembly=TestUILibrary" 
             Height="600" Width="600" Background="Transparent"> 
         <Canvas> 
             <local:UserControlTest TestText="{Binding ekTestText}" /> 
         </Canvas> 
     </ek:UIRoot> 
     


    <UserControl x:Class="TestUILibrary.UserControlTest"
                 x:Name="uct"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
        <TextBlock Text="{Binding Path=TestText, ElementName=uct}" />
    </UserControl>
    


    and finally in the .xaml.cs
        public partial class UserControlTest : UserControl
        {
            public UserControlTest()
            {
                InitializeComponent();
            }
    
            public string TestText
            { get; set; }
    
            public static readonly DependencyProperty TestTextProperty =
                 DependencyProperty.Register("TestText", typeof(string),
                 typeof(UserControlTest), new FrameworkPropertyMetadata(string.Empty));
        }
    


    As you said above this last file won't actually doing anything - but putting properties in here makes Visual Studio more happy.

    TestUILibrary now compiles correctly, but when I try to build my main project with ekRoot1 and UserControlTest added, I get the following error:

    ... GeneratedUI\ekRoot1.xaml.cs(49,49,49,65): error CS0117: 'EmptyKeys.UserInterface.Generated.UserControlTest' does not contain a definition for 'TestTextProperty'

    Is this sort of binding not currently supported, or is there something I should be doing here?

    Thanks again.
    Filip DušekUser is Offline
    Advanced Member
    Advanced Member
    Posts:693


    --
    01 Sep 2015 05:31 PM
    You would have to change UI Generator to be able to use custom dependency properties for your user control. Easier is just to use data binding on data context.

    I have one parent view model, which contains other view models. So for example Main Menu is using LoadGame user control with LoadGameViewModel. This way you don't have to make dependency property for each "stuff" in user control and you can actually separate code so your view models are not that big.

    <GameMenuControls:LoadGame Margin="20" DataContext="{Binding LoadGameViewModel}" />
    


    "The tag 'UserControlTest' does not exist in XML namespace" issue is usually Visual Studio designer issue. Closing designer and rebuilding helps ... sometime. For that and many other reasons I have user controls in separate assembly from the rest.
    JekevUser is Offline
    New Member
    New Member
    Posts:3


    --
    01 Sep 2015 05:52 PM
    Thanks - I now have it everything working
    Arek KaźmierowskiUser is Offline
    New Member
    New Member
    Posts:63


    --
    15 Dec 2015 11:37 PM
    I have some problems with UserControl as well. It might be related to the fact that my last WPF development was some two years ago..

    I created things like above - I have now the GameLibrary, UI project with UiRoot.xaml, and another UI project with user controls and main game project. The two UI projects generate UI with post build step.

    And what I'm trying to do is typical game UI with main menu, settings menu. I don't really know how to switch between menus having just one UI core. I did something like:

    <ek:UIRoot
        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"
        xmlns:ek="clr-namespace:EmptyKeys.UserInterface.Designer;assembly=EmptyKeys.UserInterface.Designer"
        xmlns:c="clr-namespace:EmptyKeys.UserInterface.Designer.Charts;assembly=EmptyKeys.UserInterface.Designer"
        xmlns:controls="clr-namespace:PotBlack.UI.Design.Controls;assembly=PotBlack.UI.Design.Controls"
        mc:Ignorable="d" 
        d:DesignHeight="640" d:DesignWidth="500"
        FontSize="22" FontFamily="Usuzi Condensed" Background="#00000000">
        <Grid>
            <controls:UiQuestionMenu />
            <controls:UiMainMenu />
        </Grid>
    </ek:UIRoot>
    


    and wanted to show / hide user controls (UiMainMenu, UiQuestionMenu) based on a property in the view model. But I can't get BooleanToVisibility converter to work (it says "not supported").
    Also considered using DataTemplate to generate menu UI from the ViewModel type, but I don't think I can do this if my view models are in the "GameLibrary" which is not references in the UI projects.

    I must be missing something simple, but what is it?
    Filip DušekUser is Offline
    Advanced Member
    Advanced Member
    Posts:693


    --
    16 Dec 2015 12:18 AM
    Hi, BooleanToVisibility converter is automatic, just don't specify any.
    Arek KaźmierowskiUser is Offline
    New Member
    New Member
    Posts:63


    --
    16 Dec 2015 09:23 AM
    Thanks, this works. I don't know if it's doing Hidden or Collapsed in case of false, but it just works anyway when placed in a grid
    Filip DušekUser is Offline
    Advanced Member
    Advanced Member
    Posts:693


    --
    16 Dec 2015 09:44 AM
    false or null is Collapsed
    ellisonchUser is Offline
    New Member
    New Member
    Posts:23


    --
    05 Jul 2016 03:55 AM
    I am having trouble with this same issue. I have tried the above suggestions, and everything else I can think of, but cannot reference my own UserControl inside of the BasicUI. Can you please update https://github.com/EmptyKeys/UI_Examples to show how this is to be done? The only UserControl you have there is the TetrisBlock, which is referenced dynamically.

    It should be super simple:
    - Add to the UserInterface project a MyUserControl.xaml containing a simple UserControl
    - In BasicUI.xaml:
    -- Adding some kind of xmlns for it (e.g., 'controls')
    -- Adding some kind of static reference to the control (e.g.,
    <controls:MyUserControl/>
    )

    Between project dependencies, VS code-behind, etc., I just cannot get it to work. I've tried it with separate projects, the same project, with keeping code-behind, with removing it. Everything has different errors.
    Filip DušekUser is Offline
    Advanced Member
    Advanced Member
    Posts:693


    --
    05 Jul 2016 09:56 AM
    OK, as soon as I have some spare time.

    BTW it's actually that super simple with few "issues":

    - it's best to have separate project for user controls
    - you have to use full assembly xmlns with assembly name
    - you have to use -bd="$(TargetDir)\" command line option for UI Generator
    - and keep code-behind
    ellisonchUser is Offline
    New Member
    New Member
    Posts:23


    --
    05 Jul 2016 04:22 PM
    I tried again from the beginning.

    1) I took your latest BasicUI_Monogame example from github.
    2) Added a new project for UIControls
    3) Gave it a simple MyUserControl.xaml
    4) Added a second new project for the output of running EmptyKeys against the new xaml (calling it GameUILibraryControls)
    5) Configured the build step in UIControls to output to a GeneratedUI directory inside of GameUILibraryControls
    6) Make GameUILibraryControls depend on UIControls
    7) Added a reference to GameUILibraryControls from the old UserInterface project
    8) Added a
       <br />    to ek:UIRoot in BasicUI.xaml    <br />    9) Added    <br />   [CODE]<controls:MyUserControl/>

    to the BasicUI

    * I can't figure out how to get your forum software to stop eating my code above. I guess you'll have to quote my post to see what it is.

    At this point I get the following errors
    - #error: &#39;&#39;The invocation of the constructor on type &#39;EmptyKeys.UserInterface.Generated.MyUserControl&#39; that matches the specified binding constraints threw an exception.&#39; Line number &#39;15&#39; and line position &#39;550&#39;.&#39;
    - A value of type &#39;MyUserControl&#39; cannot be added to a collection or dictionary of type &#39;UIElementCollection&#39;.
    - The name "MyUserControl" does not exist in the namespace "clr-namespace:EmptyKeys.UserInterface.Generated;assembly=GameUILibraryControls".
    

    from BasicUI.xaml.

    I tried adding an additional reference to UIControls from UserInterface, and that doesn't help. I've also tried without using separate projects (as this seems like the technically superior solution), but I couldn't get that to work either. If separate projects *are* required, does that mean I would have to make another project (or 2?) if my user control used another user control?

    I feel like I've tried everything I can possibly think of. I'm looking forward to your solution.
    Arek KaźmierowskiUser is Offline
    New Member
    New Member
    Posts:63


    --
    06 Jul 2016 10:11 AM
    Did you include the files generated in GeneratedUI into the project?
    ellisonchUser is Offline
    New Member
    New Member
    Posts:23


    --
    06 Jul 2016 02:47 PM
    Yes
    Arek KaźmierowskiUser is Offline
    New Member
    New Member
    Posts:63


    --
    06 Jul 2016 03:37 PM
    Just noticed that you don't seem to have a separate project for UserControls. Your user control needs to be in a separate project than your ek:UIRoot which is consuming it, and both projects need to have a post-build step to run the generator.

    If you're creating this user control just for sake of separating code and not to reuse it, you might be better off putting this part into main XAML and forget the UserControl...
    ellisonchUser is Offline
    New Member
    New Member
    Posts:23


    --
    06 Jul 2016 04:09 PM
    Making a new controls project was step 2. Configuring the post-build step to run the generator for the new project is step 5. It doesn't work (for me).
    Arek KaźmierowskiUser is Offline
    New Member
    New Member
    Posts:63


    --
    07 Jul 2016 02:15 PM
    hmm, where is your ek:UIRoot then? Not in GameUILibraryControls right?

    I think you're probably confusing something there. The projects with XAML files should not be used anywhere in your application / game code, nor referenced. They only exist to let the WPF designer work, and to let generator generator code out of them. So do not use them anywhere directly and don't reference them in your game. Add post-build steps to them so they generate code to some project which does contain your game, and also set dependencies so they are build before anything else.

    Your game is only using the generated code, the CS files.

    This means, if you want to use UserControls, you need two XAML projects, one referencing another one, both not referenced by any of your game project, and both generating output in the post build steps to some of your game projects.

    If you go without user controls, one XAML project is enough.

    Filip DušekUser is Offline
    Advanced Member
    Advanced Member
    Posts:693


    --
    07 Jul 2016 02:30 PM
    I will add User Control to MonoGame example on GitHub this weekend, so it's clear how to do that. Guess it's too much voodoo to figure it out.
    ellisonchUser is Offline
    New Member
    New Member
    Posts:23


    --
    07 Jul 2016 02:30 PM
    The steps I wrote above started with step 1, using Filip's BasicUI_Monogame example project checked in to github (https://github.com/EmptyKeys/UI_Examples). The suggestions you made are already satisfied by this project. I performed steps 1--9 on top of this project.

    If you want to help, take the same project, fork it, and get an example of user controls working; then you can just show me.

    (This was meant in response to Arek)
    ellisonchUser is Offline
    New Member
    New Member
    Posts:23


    --
    07 Jul 2016 02:43 PM
    Filip, if it's possible to do it without additional projects (you said above "it's best to have separate project", not that it's required), it might be worth demonstrating. Especially if a user control uses another user control would require three total projects. It seems like it might get a bit unwieldy.
    You are not authorized to post a reply.
    Page 1 of 212 > >>