User avatar
Scherub
Topic Author
Posts: 141
Joined: 06 May 2014, 20:53
Contact:

[Unity] Various questions

15 May 2014, 01:05

This time I have various questions. :)

1. Is there a simple way to react to a RETURN input within a TextBox, say for a simple chat box? As there are no behaviors the only way I see right now is to parse the bound property for a LineBreak, after allowing the TextBox to accept enter. Is there a better way?


2. Another thing where I'm not sure how to implement it is how to scroll to the end of a TextBox or ListBox without behaviors. Sure, I could attach a code behind within Unity but that's not really a good option when there are too many elements around that would all need a 'code behind' file.


3. What is the best way to change the color of a ProgressBar depending on the value without being able to use a ValueConverter? Let's say I have a range from 0 to 100 and I want the color to be red when it's under 20 and yellow when it's between 21 and 40. Otherwise it would be green. Now I want a smooth animation of the progress and the color change (the interpolation itself isn't the problem). Can you give me any hints?


4. With the implementation of inline formatting that you mentioned in another thread will it also be possible to use icons/symbols?


5. When I were implementing my draggable window I had trouble when the mouse left the control (because the mouse pointer moves too fast) as it would stop receiving the appropriate events and thus stop dragging the window. Usually I would use CaptureMouse() / ReleaseMouseCapture() to get around this problem. But somehow I don't receive any events any more after calling CaptureMouse(). Is this a bug or am I doing something wrong?


6. For testing purposes I implemented a timer in a VM with an interval of 250ms. Now when I press Play within the Unity Editor it also starts the timer and everything seems to work as expected. But the problem begins when I stop the editor as the timer continues to run.

I tried then overriding the Dispose() method of the VM (inherited from SerializableComponent) but Dispose() was only called when Unity had to recompile a script. On the other hand it calls Dispose() by stopping the editor when the timer isn't running.

Oh, and when I override the Dispose() method and stop the editor while the timer is still running it will open five "Unhandled Noesis Exceptions!" (Access Violation - Noesis.dll!BaseExpression_GetEvaluateBehavior) and just crash Unity.
 
wckdspn
Posts: 67
Joined: 18 Aug 2012, 23:14

Re: [Unity] Various questions

15 May 2014, 02:36

1. TextBox has a KeyDown/Up event. Not sure if it is being eaten for text input, have you tried it?

2. Not sure what you want here. Do you want to control the view, or the caret?

3. Bind the color and progress bar value to properties. You can then alter the color at certain levels. If you want to animate, you can instead trigger storyboards when you hit certain levels. Or you could make them visualstates and tweak the transitions (could see this on a user control). You've got a few options.

4. You could do this now if the icons exist in your font. You could put an emoticon selector box (assuming that's the reason) that would insert the correct unicode character for the icon.

5. I've attached some simple code that defines a simple window user control (it only handles movement, no content or additional controls). This window control can be moved by clicking and dragging the top region. It will also place the current focused window to the top of the visual stack.
The second XAML is the one to attach to the Noesis Panel. It just has a few of the windows.
It's as simple and to the point as I can get it.
using UnityEngine;
using System.Collections;
using Noesis;

namespace UserControls
{
    [Noesis.Extended]
    [Noesis.UserControlSource("Assets/XAML/TestWindow.xaml")]
    public class TestWindow : Noesis.UserControl
    {
        StackPanel         _topbarPanel;
        TranslateTransform _gridTranslation;

        float _initialX;
        float _initialY;

        public void OnPostInit()
        {
            _gridTranslation = FindName<TranslateTransform>("GridTranslation");
            _topbarPanel     = FindName<StackPanel>("TopBar");

            MouseDown                        += OnMouseDown;
            _topbarPanel.MouseLeftButtonDown += TopBar_MouseDown;
            _topbarPanel.MouseLeftButtonUp   += TopBar_MouseUp;
            _topbarPanel.MouseMove           += TopBar_MouseMove;
        }

        void OnMouseDown(BaseComponent arg0, MouseButtonEventArgs arg1)
        {
            //Send to top of UI stack
            var parent = this.GetParent().As<Panel>();
            if (parent != null)
            {
                var children = parent.GetChildren();
                if (children.Count() > 1)
                {
                    children.Remove(this);
                    children.Add(this);
                }
            }
        }

        void TopBar_MouseDown(BaseComponent arg0, MouseButtonEventArgs arg1)
        {
            var container = arg0.As<FrameworkElement>();
            if (container != null)
            {
                container.CaptureMouse();
                _initialX = arg1.position.x - _gridTranslation.GetX();
                _initialY = arg1.position.y - _gridTranslation.GetY();
            }
        }

        void TopBar_MouseUp(BaseComponent arg0, MouseButtonEventArgs arg1)
        {
            var container = arg0.As<FrameworkElement>();
            if (container != null)
            {
                container.ReleaseMouseCapture();
            }
        }

        void TopBar_MouseMove(BaseComponent arg0, MouseEventArgs arg1)
        {
            var container = arg0.As<FrameworkElement>();

            if (container != null && container.GetIsMouseCaptured() && _gridTranslation != null)
            {
                float newX = arg1.position.x - _initialX;
                float newY = arg1.position.y - _initialY;

                _gridTranslation.SetX(newX);
                _gridTranslation.SetY(newY);
            }
        }
    }
}
<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	x:Class="UserControls.TestWindow"
	UseLayoutRounding="true"
>
  <Grid Background="#FFF4F6F9" Width="300" Height="400">
    <Grid.RenderTransform>
      <TranslateTransform x:Name="GridTranslation" X="0" Y="0" />
    </Grid.RenderTransform>
    <StackPanel x:Name="TopBar" Height="10" VerticalAlignment="Top" Background="#FF767575"/>
  
  </Grid>
</UserControl>
<Canvas
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:usercontrols="clr-namespace:UserControls"
  UseLayoutRounding="true">
  <usercontrols:TestWindow />
  <usercontrols:TestWindow />
  <usercontrols:TestWindow />
  <usercontrols:TestWindow />
  <usercontrols:TestWindow />
</Canvas>
6. What are you trying to accomplish? Do note, that Timer runs on a separate thread.
 
User avatar
jsantos
Site Admin
Posts: 4266
Joined: 20 Jan 2012, 17:18
Contact:

Re: [Unity] Various questions

15 May 2014, 19:16

1. TextBox has a KeyDown/Up event. Not sure if it is being eaten for text input, have you tried it?
I think that the best way to do this, a chat control, is by having a ListBox and a single line TextBlock. Whenever the TextInput event (when the user press enter) of the TextBlock is raised the content is added to the end of the ListBox and the TextBlock is cleared.

Yes, we should create a Chat style control as a sample.

Thaks for your collaboration wckdspn!
 
User avatar
Scherub
Topic Author
Posts: 141
Joined: 06 May 2014, 20:53
Contact:

Re: [Unity] Various questions

17 May 2014, 16:39

Thank you for your answers. :)

1. The problem I'm having is that I'm following the MVVM-pattern and thus I don't have access to the TextBox. In order to change that I have afaik two options using Noesis: a) attach another 'code behind' file within Unity or write a user control. If there is another option I would be glad to hear it. In WPF I could write a small behavior and attach it to the TextBox.

2. This problem is similar to the first one. I don't have access to the TextBlock/Box or the ListBox so I can't control the caret, the displayed items within a listbox or anything, unless I attach another 'code behind' file within Unity or create a UserControl.

I guess my main problem is that I still haven't figured out what the 'best' way is to structure and connect all components. Unfortunately nearly all Noesis Unity Samples are implemented using XAML only without actually showing how you would use it within a real application.

3. Right now I'm exactly doing that (using a Brush property) but I'm not really satisfied going this way. A much better way would probably be to use a ValueConverter. Unfortuantely I didn't have the time to animate it yet so that's one of the tasks I'm going to do next.

4. I'll leave that out for now as I have to gather more information about it first. Is there a tutorial or so about using fonts in Noesis somewhere?

5. Okay, there are two main differences between your code and mine. You used the sender of the event to capture the mouse. I just used the header bar. So that was my bad. :) The other one is how you change the focus. You just remove the control and add it back to the collection. I wrote an extension method to the FrameworkElement that I call that determines the max Z-value of all siblings and then sets the value of the clicked control to maxZ + 1.

6. As I said I used the timer just for testing purposes to get quick results (constantly changing the values of various progressbars). And yes, I'm aware of that the timer runs on a separate thread. So I understood that it would continue running after I stopped the editor. That's the reason why I tried to stop and clean up the timer when the editor was stopped, using the Dispose() method of the views view model. But I didn't expect it to crash Noesis and with it Unity.


Again, thanks a lot for your answers. :)
 
User avatar
Scherub
Topic Author
Posts: 141
Joined: 06 May 2014, 20:53
Contact:

Re: [Unity] Various questions

19 May 2014, 07:43

Even if not all of the previous questions/problems are solved I'll ask a few more. The problem is also that I don't know what is already as a bug so I keep asking here.

7. I turned the Noesis-logging to a file on so I get a file NoesisGUI.play.log. Unfortunately it keeps telling me that even the simplest bindings fail, even though they work when I run the scene.

8. Sometimes Unity keeps constantly re-aquiring the focus. The solution is to click into the "Game" view within Unity and then I can focus other windows outside of Unity again. This has probably something to do with Noesis as I never experienced this before using Noesis.

9. When I create a ProgressBar with no width set and apply an animation to increase it's current value to the max value it will change the value to max and then increase the width of the ProgressBar to 'infinite'.

10. Another problem with the ProgressBar. When I try to animate the value change by reacting to an EventTrigger called "RangeBase.ValueChanged" it doesn't work properly. It works in WPF though. It seems to react to the trigger the first time it's called and it looks like it has something to do with the To-property of an animation being bound to a value. I'll give you a very simple example.
<ProgressBar Value="{Binding Value}" Maximum="100" Width="100">
	<ProgressBar.Triggers>
		<EventTrigger RoutedEvent="RangeBase.ValueChanged">
			<BeginStoryboard>
				<Storyboard>
					<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Value" To="{Binding Value}" />
				</Storyboard>
			</BeginStoryboard>
		</EventTrigger>
	</ProgressBar.Triggers>
</ProgressBar>
11. I have a value bound to the SelectedItem-Property of a ListBox. Now when I select an item in the UI the setter of the property is called twice.

12. ListBox: I have to explicitely state that the SelectedItem-Property is bound to a value using a TwoWay-binding otherwise it doesn't work.

13. And the ListBox again: When I assign an item to SelectedItem within the constructor of a ViewModel it won't work as after leaving the constructor null will be assigned again. Also OnPostInit() doesn' work on ViewModels so right now there doesn't seem to be a way around this problem.

14. Can I apply the Extended-Attribute only to non-generic classes? Are there any plans to change that?

15. I'm not able get nested property-bindings working even though everything is inherited from BaseComponent. A simple example: I have a collection with characters bound to a ListBox. When I select an item it will also set the value of the SelectedCharacter-property of the ViewModel. Until there everything is working. But when I try to bind to a property of the SelectedCharacter the binding doesn't seem to work.
<TextBlock Text={Binding SelectedCharacter.Name} />
16. I have also trouble with the binding when I fill the content of my DraggableWindow. Could you give me a simple example of a self-made UserControl that I can apply content to where the binding still works, please?
 
User avatar
sfernandez
Site Admin
Posts: 3222
Joined: 22 Dec 2011, 19:20

Re: [Unity] Various questions

19 May 2014, 14:25

1. Is there a simple way to react to a RETURN input within a TextBox, say for a simple chat box? As there are no behaviors the only way I see right now is to parse the bound property for a LineBreak, after allowing the TextBox to accept enter. Is there a better way?
I would create a ChatBox UserControl which manages the text box and list of messages as you want. Then you can use that chat box anywhere. To check for a Return key press, you just add a handler to the KeyDown event of the chat TextBox in the user control code behind. You can continue using MVVM with UserControls, you just have to set your ViewModel on the control and use bindings from the view model.
2. Another thing where I'm not sure how to implement it is how to scroll to the end of a TextBox or ListBox without behaviors. Sure, I could attach a code behind within Unity but that's not really a good option when there are too many elements around that would all need a 'code behind' file.
I don't understand what exactly what you are asking for. Maybe you are talking of making visible a certain message within the chat box. If that is the case, you can use the method BringIntoView().
3. What is the best way to change the color of a ProgressBar depending on the value without being able to use a ValueConverter? Let's say I have a range from 0 to 100 and I want the color to be red when it's under 20 and yellow when it's between 21 and 40. Otherwise it would be green. Now I want a smooth animation of the progress and the color change (the interpolation itself isn't the problem). Can you give me any hints?
You can have in your ViewModel the Value of the ProgressBar, and calculate the color based on this value. Then you expose in the ViewModel that calculated color (Brush) and you bind it to the ProgressBar (for example to the Foreground property, and have a template that uses Foreground as the color for the PART_Indicator element).
4. With the implementation of inline formatting that you mentioned in another thread will it also be possible to use icons/symbols?
Only icons/symbols defined in a font file, so they would be monochrome, as any other character you write.
5. When I were implementing my draggable window I had trouble when the mouse left the control (because the mouse pointer moves too fast) as it would stop receiving the appropriate events and thus stop dragging the window. Usually I would use CaptureMouse() / ReleaseMouseCapture() to get around this problem. But somehow I don't receive any events any more after calling CaptureMouse(). Is this a bug or am I doing something wrong?
You should be able to capture mouse events by calling CaptureMouse(). If this is failing for you, please create a bug report in our bugtracker and attach a test to reproduce it, we will take a look and help you with it.
6. For testing purposes I implemented a timer in a VM with an interval of 250ms. Now when I press Play within the Unity Editor it also starts the timer and everything seems to work as expected. But the problem begins when I stop the editor as the timer continues to run.

I tried then overriding the Dispose() method of the VM (inherited from SerializableComponent) but Dispose() was only called when Unity had to recompile a script. On the other hand it calls Dispose() by stopping the editor when the timer isn't running.
I don't know if you are keeping references to your VM in any script component, but you should know that Unity doesn't delete script components immediately. You can use OnDestroy() message to reset references to the VM before you stop playing.
Oh, and when I override the Dispose() method and stop the editor while the timer is still running it will open five "Unhandled Noesis Exceptions!" (Access Violation - Noesis.dll!BaseExpression_GetEvaluateBehavior) and just crash Unity.
Please report this bug in the bugtracker. We want to fix any possible crash our customers find in NoesisGUI.
7. I turned the Noesis-logging to a file on so I get a file NoesisGUI.play.log. Unfortunately it keeps telling me that even the simplest bindings fail, even though they work when I run the scene.
Maybe the binding fails when xaml is loaded and initialized, but it is solved when ViewModel is set. Could this be what you are experiencing?
8. Sometimes Unity keeps constantly re-aquiring the focus. The solution is to click into the "Game" view within Unity and then I can focus other windows outside of Unity again. This has probably something to do with Noesis as I never experienced this before using Noesis.
NoesisGUI uses Unity's OnApplicationFocus() message to enable/disable input events. Unity calls this message with a false param any time you click outside the Game view inside the editor. And calls it again with a false param only when Game view is clicked again.
9. When I create a ProgressBar with no width set and apply an animation to increase it's current value to the max value it will change the value to max and then increase the width of the ProgressBar to 'infinite'.
Could you attach the xaml here? Any UI element normally adapts to the space that its parent container reserves for it.
10. Another problem with the ProgressBar. When I try to animate the value change by reacting to an EventTrigger called "RangeBase.ValueChanged" it doesn't work properly. It works in WPF though. It seems to react to the trigger the first time it's called and it looks like it has something to do with the To-property of an animation being bound to a value. I'll give you a very simple example.
<ProgressBar Value="{Binding Value}" Maximum="100" Width="100">
	<ProgressBar.Triggers>
		<EventTrigger RoutedEvent="RangeBase.ValueChanged">
			<BeginStoryboard>
				<Storyboard>
					<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Value" To="{Binding Value}" />
				</Storyboard>
			</BeginStoryboard>
		</EventTrigger>
	</ProgressBar.Triggers>
</ProgressBar>
This problem is already reported. There is a bug in our code that makes bindings in Freezable elements (as the DoubleAnimation in your example) don't work when Binding.Source is DataContext. Maybe you can use a binding to a named element as a workaround until we fix it.
11. I have a value bound to the SelectedItem-Property of a ListBox. Now when I select an item in the UI the setter of the property is called twice.

12. ListBox: I have to explicitely state that the SelectedItem-Property is bound to a value using a TwoWay-binding otherwise it doesn't work.

13. And the ListBox again: When I assign an item to SelectedItem within the constructor of a ViewModel it won't work as after leaving the constructor null will be assigned again. Also OnPostInit() doesn' work on ViewModels so right now there doesn't seem to be a way around this problem.
I will take a look at these issues and let you know. It would be better if you report it in the bugtracker to follow the status of these issues.
14. Can I apply the Extended-Attribute only to non-generic classes? Are there any plans to change that?
We have plans to improve C# API so it can use .NET default classes, so it would be easier for people coming from WPF world to work with NoesisGUI. Now our API is still very tied to the native C++ code and their classes.
15. I'm not able get nested property-bindings working even though everything is inherited from BaseComponent. A simple example: I have a collection with characters bound to a ListBox. When I select an item it will also set the value of the SelectedCharacter-property of the ViewModel. Until there everything is working. But when I try to bind to a property of the SelectedCharacter the binding doesn't seem to work.
<TextBlock Text={Binding SelectedCharacter.Name} />
I created the following simple xaml:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <TextBlock Text="{Binding SelectedCharacter.Name}"/>
</Grid>
With the following code behind script attached to the NoesisGUIPanel:
using UnityEngine;
using System;
using Noesis;

[Extended]
class SelectedCharacter : BaseComponent
{
    string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            if (_name != value)
            {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }
    }
}

[Extended]
class MyViewModel : BaseComponent
{
    SelectedCharacter _selectedCharacter;
    public SelectedCharacter SelectedCharacter
    {
        get
        {
            return _selectedCharacter;
        }
        set
        {
            if (_selectedCharacter != value)
            {
                _selectedCharacter = value;
                NotifyPropertyChanged("SelectedCharacter");
            }
        }
    }
}

public class _Test : MonoBehaviour
{
    void Start()
    {
        var gui = GetComponent<NoesisGUIPanel>();
        var root = gui.GetRoot<Grid>();
        MyViewModel viewModel = new MyViewModel
        {
            SelectedCharacter = new SelectedCharacter { Name = "Peter" }
        };
        root.SetDataContext(viewModel);
    }
}
And it worked correctly. Could you attach an excerpt of your sample that is failing?
16. I have also trouble with the binding when I fill the content of my DraggableWindow. Could you give me a simple example of a self-made UserControl that I can apply content to where the binding still works, please?
Ok, here you have the xaml & code of a sample window control:
<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="WindowControl">
    <StackPanel>
        <Border Background="SkyBlue" CornerRadius="2,2,0,0" Padding="20,1">
            <TextBlock Text="{Binding Title}" Foreground="White" FontWeight="Bold" FontSize="20" HorizontalAlignment="Center"/>
        </Border>
        <Border BorderBrush="SkyBlue" BorderThickness="2,0,2,2" Background="#80DFEFFF" CornerRadius="0,0,2,2" Padding="5">
            <ContentPresenter Content="{Binding Child}"/>
        </Border>
    </StackPanel>
</UserControl>
[Extended]
[UserControlSource("Assets/Sample/WindowControl.xaml")]
public class WindowControl : Noesis.UserControl
{
    string _title;
    public string Title
    {
        get
        {
            return _title;
        }
        set
        {
            if (_title != value)
            {
                _title = value;
                NotifyPropertyChanged("Title");
            }
        }
    }

    Noesis.BaseComponent _child;
    public Noesis.BaseComponent Child
    {
        get
        {
            return _child;
        }
        set
        {
            if (_child != value)
            {
                _child = value;
                NotifyPropertyChanged("Child");
            }
        }
    }

    public WindowControl()
    {
        SetDataContext(this);
    }
}
And you can use this user control in another xaml like this:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <WindowControl Title="Some window" HorizontalAlignment="Center" VerticalAlignment="Center">
        <WindowControl.Child>
            <StackPanel>
                <TextBlock Text="Some text in the window" Margin="0,0,0,10"/>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
                    <Button Content="OK" Width="100"/>
                    <Button Content="Cancel" Width="100" Margin="8,0,0,0"/>
                </StackPanel>
            </StackPanel>
        </WindowControl.Child>
    </WindowControl>
</Grid>
 
User avatar
Scherub
Topic Author
Posts: 141
Joined: 06 May 2014, 20:53
Contact:

Re: [Unity] Various questions

19 May 2014, 22:10

Thanks for your detailled post! :) I'll just reply to a few points for now and get back to answer some more later.
2. Another thing where I'm not sure how to implement it is how to scroll to the end of a TextBox or ListBox without behaviors. Sure, I could attach a code behind within Unity but that's not really a good option when there are too many elements around that would all need a 'code behind' file.
I don't understand what exactly what you are asking for. Maybe you are talking of making visible a certain message within the chat box. If that is the case, you can use the method BringIntoView().
Okay, I'll try to explain it again. The problem isn't exactly what method to call. The problem is how to access the ListBox in a simple view. There are only two solutions to that:

1. I create a 'code behind' file that I have to attach to the camera. But if I would start doing that I would end up with hundreds of so-called 'code behind' scripts attached to the camera. So that's not really an option.

2. I create a user control. For the case with the chat box it might be a good idea. But that would also mean that I have to create user controls even for the simplest test just for the sake of being able to access the control by code.
I will take a look at these issues and let you know. It would be better if you report it in the bugtracker to follow the status of these issues.
If I knew what bugs are already reported I would do that but as I have no clue what issues are already on your list I will just stay away from it for two reasons: a) It would mean more work for you as you would have to maintain the status of the same issue multiple times. b) If I write it here other people may read it and know it's a known issue.
14. Can I apply the Extended-Attribute only to non-generic classes? Are there any plans to change that?
We have plans to improve C# API so it can use .NET default classes, so it would be easier for people coming from WPF world to work with NoesisGUI. Now our API is still very tied to the native C++ code and their classes.
Sounds promising! :)

@16: Thanks for your example but unfortunately you missed the important bit. You created a WindowControl with two properties. But if you would want to bind to those properties in your code then you would have to use DependencyProperties, wouldn't you? So in your last xaml instead of setting the title and the child-content directly within the xaml you would want to bind them to properties of the VM that you would have to set up first. That's the thing that I can't get to work. Can you give me an example for this as well, please?
 
User avatar
Scherub
Topic Author
Posts: 141
Joined: 06 May 2014, 20:53
Contact:

Re: [Unity] Various questions

20 May 2014, 00:34

@10. Okay, I followed your advice, created a named element (first a TextBox, then a ContentControl) and bound the value of the progressbar to the text/value of this element. But it still doesn't work. Can you give me another hint, please?

Here is the current xaml:
<DataTemplate x:Key="NeedDataTemplate">
	<ProgressBar Grid.Column="1" Height="8" Maximum="{Binding MaxValue}" Value="{Binding CurrentValue, Mode=OneWay}" 
				  ToolTip="{Binding Tooltip}" Style="{StaticResource VitalProgressBarStyle}" Margin="5,0">
		<ProgressBar.Triggers>
			<EventTrigger RoutedEvent="RangeBase.ValueChanged">
				<BeginStoryboard>
					<Storyboard>
						<DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Value" To="{Binding Content, ElementName=Temp}" />
					</Storyboard>
				</BeginStoryboard>
			</EventTrigger>
		</ProgressBar.Triggers>
	</ProgressBar>
	<!--<TextBlock Grid.Column="2" x:Name="Temp" Text="{Binding CurrentValue}" Margin="5,0" />-->
	<ContentControl Grid.Column="2" x:Name="Temp" Content="{Binding CurrentValue, Mode=TwoWay}" Margin="5,0" />
</DataTemplate>
 
User avatar
sfernandez
Site Admin
Posts: 3222
Joined: 22 Dec 2011, 19:20

Re: [Unity] Various questions

20 May 2014, 18:41

Okay, I'll try to explain it again. The problem isn't exactly what method to call. The problem is how to access the ListBox in a simple view. There are only two solutions to that:

1. I create a 'code behind' file that I have to attach to the camera. But if I would start doing that I would end up with hundreds of so-called 'code behind' scripts attached to the camera. So that's not really an option.

2. I create a user control. For the case with the chat box it might be a good idea. But that would also mean that I have to create user controls even for the simplest test just for the sake of being able to access the control by code.
With current NoesisGUI features, I will go for the option number 2, using UserControls for your panels, and connect the ViewModel to the UserControl code-behind.
If I knew what bugs are already reported I would do that but as I have no clue what issues are already on your list I will just stay away from it for two reasons: a) It would mean more work for you as you would have to maintain the status of the same issue multiple times. b) If I write it here other people may read it and know it's a known issue.
This is something we are studying, because sharing all reported bugs has better visibility on what is being worked on. But we are concerned about the privacy of the customers, and the data they could be sharing with us through the bugtracker to help us solve the bugs.

About (a) it is not really a big problem as we can establish relationships between issues.

What I would suggest, if you don't mind, is to create a topic for each issue (or group of related issues), instead of having a huge post with lots of questions. I think it becomes hard to follow a discussion line if there are so many different points to discuss. What do you think? :)
@16: Thanks for your example but unfortunately you missed the important bit. You created a WindowControl with two properties. But if you would want to bind to those properties in your code then you would have to use DependencyProperties, wouldn't you? So in your last xaml instead of setting the title and the child-content directly within the xaml you would want to bind them to properties of the VM that you would have to set up first. That's the thing that I can't get to work. Can you give me an example for this as well, please?
Ok, as you guessed, Title and Child should be DependencyProperties to support bindings. The WindowControl code will look like this then:

NOTE: If we are going to set WindowControl properties from a user DataContext, we cannot do SetDataContext(this) in WindowControl constructor. So bindings in the WindowControl.xaml should use a named element.
<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="WindowControl"
  x:Name="Root">
    <StackPanel>
        <Border Background="SkyBlue" CornerRadius="2,2,0,0" Padding="20,1">
            <TextBlock Text="{Binding Title, ElementName=Root}" Foreground="White" FontWeight="Bold" FontSize="20" HorizontalAlignment="Center"/>
        </Border>
        <Border BorderBrush="SkyBlue" BorderThickness="2,0,2,2" Background="#80DFEFFF" CornerRadius="0,0,2,2" Padding="5">
            <ContentPresenter Content="{Binding Child, ElementName=Root}"/>
        </Border>
    </StackPanel>
</UserControl>
[Extended]
[UserControlSource("Assets/Sample/WindowControl.xaml")]
public class WindowControl : Noesis.UserControl
{
    public static Noesis.DependencyProperty TitleProperty = Noesis.DependencyProperty.Register("Title",
        typeof(string), typeof(WindowControl), new Noesis.PropertyMetadata(string.Empty));

    public string Title
    {
        get { return GetValue<string>(TitleProperty); }
        set { SetValue<string>(TitleProperty, value); }
    }

    public static Noesis.DependencyProperty ChildProperty = Noesis.DependencyProperty.Register("Child",
        typeof(Noesis.BaseComponent), typeof(WindowControl), new Noesis.PropertyMetadata(null));

    public Noesis.BaseComponent Child
    {
        get { return GetValue<Noesis.BaseComponent>(ChildProperty); }
        set { SetValue<Noesis.BaseComponent>(ChildProperty, value); }
    }

    public WindowControl()
    {
    }
}
And the main xaml where this control is used could look like this:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  
    <WindowControl HorizontalAlignment="Center" VerticalAlignment="Center"
        Title="{Binding DataTitle}"
        Child="{Binding DataChild}"/>

</Grid>
[Extended]
class DataViewModel : Noesis.BaseComponent
{
    string _title;
    public string DataTitle
    {
        get { return _title; }
        set
        {
            if (_title != value)
            {
                _title = value;
                NotifyPropertyChanged("DataTitle");
            }
        }
    }

    Noesis.BaseComponent _child;
    public Noesis.BaseComponent DataChild
    {
        get { return _child; }
        set
        {
            if (_child != value)
            {
                _child = value;
                NotifyPropertyChanged("DataChild");
            }
        }
    }
}

public class _Test : MonoBehaviour
{
    void Start()
    {
        var gui = GetComponent<NoesisGUIPanel>();
        var root = gui.GetRoot<Grid>();

        Noesis.StackPanel sp = new Noesis.StackPanel();
        Noesis.TextBlock tb = new Noesis.TextBlock("Some text in the window");
        tb.SetMargin(new Thickness(0,0,0,10));
        sp.GetChildren().Add(tb);
        Noesis.StackPanel sph = new Noesis.StackPanel();
        sph.SetOrientation(Noesis.Orientation.Horizontal);
        sph.SetHorizontalAlignment(Noesis.HorizontalAlignment.Right);
        Noesis.Button ok = new Noesis.Button();
        ok.SetContent("OK");
        ok.SetWidth(100.0f);
        sph.GetChildren().Add(ok);
        Noesis.Button cancel = new Noesis.Button();
        cancel.SetContent("Cancel");
        cancel.SetWidth(100.0f);
        cancel.SetMargin(new Thickness(8,0,0,0));
        sph.GetChildren().Add(cancel);
        sp.GetChildren().Add(sph);

        DataViewModel viewModel = new DataViewModel
        {
            DataTitle = "Some Window",
            DataChild = sp
        };

        root.SetDataContext(viewModel);
    }
}
Is this what you mean? Because it worked correctly for me.
 
User avatar
Scherub
Topic Author
Posts: 141
Joined: 06 May 2014, 20:53
Contact:

Re: [Unity] Various questions

20 May 2014, 23:34

Thanks a lot for your detailled answer! :) I think we have nearly solved my problem even if I think the correct solution is not supported by NoesisGUI right now. But perhaps you can proof me wrong. :)

I tested your example and yes it works, thanks to the MonoBehaviour where you set the DataContext to the view model you created in code. I tried it the other way around, creating the view model within xaml and setting the data context in another grid. So I changed your example to fit my needs but then it didn't work any more. :( Is it even possible to do it this way as this would be a much neater solution?

A short example of what I mean:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

	<Grid.Resources>
		<DataViewModel x:Key="ViewModel" />
	</Grid.Resources>
 
    <Grid DataContext="{StaticResource ViewModel}">
        <WindowControl HorizontalAlignment="Center" VerticalAlignment="Center"
            Title="{Binding DataTitle}"
            Child="{Binding DataChild}"/>
    </Grid>
</Grid>
@Reporting bugs: Okay, I'll open up tickets then in your bug tracker tool. :)

@Splitting up topics: Will do this then. :)

@new version: How long does it usually take to get it released on Unity?

Who is online

Users browsing this forum: Google [Bot] and 4 guests