Gwynneth
Topic Author
Posts: 15
Joined: 20 Apr 2017, 18:31

Manual binding to a collection element does not work

03 Jan 2020, 11:11

I'm trying to manually re-direct bindings of a custom TextBlock control. The code below works perfectly in WPF and the first manual binding of the FontFamily also works in Noesis. The other bindings try to bind to an item in a collection. I've tried two ways: binding to the collection's item by setting the string PropertyPath and by setting the item in the binding's Source property. Both of them fail. Moreover, whenever I try to inspect the value of 'myBinding' during debugging the Unity editor crashes. Is there a different way to setup such binding in Noesis or is this a bug?
        private void BindSettings() {


            // Font.
            Bind("FontFamily", FontFamilyProperty);


            if (!AreTextStyleSettingsAvailable(out int settingsIndex)) {
                return;
            }


#if !NOESIS
            // TextSettings.
            Bind($"TextStyles[{settingsIndex}].FontSize", FontSizeProperty);
            Bind($"TextStyles[{settingsIndex}].FontWeight", FontWeightProperty, new ValueConverters.FontWeightConverter());
            Bind($"TextStyles[{settingsIndex}].FontStyle", FontStyleProperty, new ValueConverters.FontStyleConverter());
            Bind($"TextStyles[{settingsIndex}].TextDecoration", TextDecorationsProperty, new ValueConverters.TextDecorationConverter());
#else
            // TextSettings.
            Bind("FontSize", settingsIndex, FontSizeProperty);
            Bind("FontWeight", settingsIndex, FontWeightProperty, new ValueConverters.FontWeightConverter());
            Bind("FontStyle", settingsIndex, FontStyleProperty, new ValueConverters.FontStyleConverter());
            Bind("TextDecoration", settingsIndex, TextDecorationsProperty, new ValueConverters.TextDecorationConverter());
#endif


        }
        
        
        private void Bind(string propName, DependencyProperty dp, IValueConverter valueConverter = null) {


            Binding myBinding = new Binding {
                Source = TextSettings,
                Path = new PropertyPath(propName),
                Mode = BindingMode.TwoWay,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
                Converter = valueConverter
            };
            BindingOperations.SetBinding(this, dp, myBinding);

        }
        
        private void Bind(string propName, int index, DependencyProperty dp, IValueConverter valueConverter = null) {


            Binding myBinding = new Binding {
                Source = TextSettings.TextStyles[index],
                Path = new PropertyPath(propName),
                Mode = BindingMode.TwoWay,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
                Converter = valueConverter
            };
            BindingOperations.SetBinding(this, dp, myBinding);


        }
        
        
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: Manual binding to a collection element does not work

07 Jan 2020, 11:00

Binding to collection elements is something that is working, the problem should be elsewhere.
What is the converter doing? I tried a similar example without a converter and it works as expected:
namespace Testing
{
    public class MyTextBlock : Noesis.TextBlock
    {
        public void Bind(int index)
        {
            Bind($"TextStyles[{index}].FontSize", FontSizeProperty);
            Bind($"TextStyles[{index}].FontWeight", FontWeightProperty);
            Bind($"TextStyles[{index}].FontStyle", FontStyleProperty);
            Bind($"TextStyles[{index}].TextDecoration", TextDecorationsProperty);
        }

        private void Bind(string path, Noesis.DependencyProperty dp)
        {
            Binding myBinding = new Noesis.Binding
            {
                Path = new Noesis.PropertyPath(path),
                Mode = Noesis.BindingMode.TwoWay,
                UpdateSourceTrigger = Noesis.UpdateSourceTrigger.PropertyChanged
            };
            Noesis.BindingOperations.SetBinding(this, dp, myBinding);
        }
    }
}
namespace Testing
{
    public class ViewModel
    {
        public List<TextStyle> TextStyles { get; private set; }
        public ViewModel() { TextStyles = new List<TextStyle>(); }
    }

    public class TextStyle
    {
        public float FontSize { get; set; }
        public Noesis.FontWeight FontWeight { get; set; }
        public Noesis.FontStyle FontStyle { get; set; }
        public Noesis.TextDecorations TextDecoration { get; set; }
    }
}
public class TestBehavior : MonoBehaviour
{
    void Start()
    {
        NoesisView view = GetComponent<NoesisView>();

        Testing.ViewModel vm = new Testing.ViewModel();
        vm.TextStyles.Add(new Testing.TextStyle
        {
            FontSize = 12.0f,
            FontWeight = Noesis.FontWeight.Bold,
            FontStyle = Noesis.FontStyle.Normal,
            TextDecoration = Noesis.TextDecorations.None
        });
        vm.TextStyles.Add(new Testing.TextStyle
        {
            FontSize = 15.0f,
            FontWeight = Noesis.FontWeight.Light,
            FontStyle = Noesis.FontStyle.Italic,
            TextDecoration = Noesis.TextDecorations.Underline
        });

        view.Content.DataContext = vm;

        Testing.MyTextBlock txt1 = (Testing.MyTextBlock)view.Content.FindName("txt1");
        Testing.MyTextBlock txt2 = (Testing.MyTextBlock)view.Content.FindName("txt2");
        Noesis.Rectangle rect = (Noesis.Rectangle)view.Content.FindName("rect");
        rect.PreviewMouseDown += (s, e) =>
        {
            txt1.Bind(0);
            txt2.Bind(1);
        };
    }
}
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:Testing">
    <Rectangle x:Name="rect" Width="200" Height="100" Fill="Red"/>
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <local:MyTextBlock x:Name="txt1" FontFamily="Arial" Foreground="White" Text="Hello World!"/>
        <local:MyTextBlock x:Name="txt2" FontFamily="Arial" Foreground="White" Text="Hello World!"/>
    </StackPanel>
</Grid>
 
Gwynneth
Topic Author
Posts: 15
Joined: 20 Apr 2017, 18:31

Re: Manual binding to a collection element does not work

13 Jan 2020, 11:10

I've tried to narrow down the issue over the weekend but have been unable to do so. I did find that the TextDecoration property simply does not work with a ValueConverter in the binding and it will throw an error if this is done in XAML. The error does not get logged if the binding is created in code as is the case here. I've already created an issue here: https://www.noesisengine.com/bugs/view.php?id=1616

As for the bindings not working in the TextBlock everything seems to work if version 2.2.6 is used; I couldn't get it to work in 2.2.5. However, with 2.2.6 the project consistently crashes when Noesis is being reloaded. The attached images show windbg log / stack trace. I don't know how to investigate this problem any further though...

Images:
https://modungamescom-my.sharepoint.com ... A?e=7NFSvL
https://modungamescom-my.sharepoint.com ... g?e=SbEB2l
 
User avatar
sfernandez
Site Admin
Posts: 2984
Joined: 22 Dec 2011, 19:20

Re: Manual binding to a collection element does not work

16 Jan 2020, 12:48

Thanks for the report, we will solve it as soon as possible.
However, with 2.2.6 the project consistently crashes when Noesis is being reloaded. The attached images show windbg log / stack trace. I don't know how to investigate this problem any further though...
Could you please create another ticket and attach your project so we can debug what is happening during reloading. We fixed many things related to this issue in the last version, but it seems it affected your project in a way we haven't tested.
 
Gwynneth
Topic Author
Posts: 15
Joined: 20 Apr 2017, 18:31

Re: Manual binding to a collection element does not work

17 Jan 2020, 12:08

Issue has been created: #1621

Who is online

Users browsing this forum: Bing [Bot] and 12 guests