none
[UWP][C#] Problem with x:Bind to Static Class RRS feed

  • Question

  • I'm having difficulties binding buttons on a calculator that I made to my static class. 

    <Button Height="45" Width="75" Background="{ThemeResource SystemControlAcrylicElementBrush}" Content="0" FontSize="24"
                            Name="ZeroButton" Margin="5,5,0,5" Click="{x:Bind NumberClicked}">
                        <Button.KeyboardAccelerators>
                            <KeyboardAccelerator Key="NumberPad0"/>
                        </Button.KeyboardAccelerators>
                    </Button>


    Public NewCalculator()
            {
                this.InitializeComponent();
                NFCalculatorViewModel nfViewModel = new NFCalculatorViewModel();
                DataContext = NFCalculatorViewModel.NFBManager;
            }
    
            NFCalculatorViewModel nfViewModel { get; set; }
     public class NFCalculatorViewModel
        {
            #region Declarations
            private static ButtonManager nfbManager = new ButtonManager();
            public static ButtonManager NFBManager { get { return nfbManager; } }
    
            private static Calculator calculator = new Calculator();
            public static Calculator Calculator { get { return calculator; } }
            #endregion
    
            public NFCalculatorViewModel()
            {
                nfbManager = new ButtonManager();
                nfbManager.InitializeCollections();
                nfbManager.UpdateNFButtons();
            }
    public class ButtonManager : INotifyCollectionChanged, INotifyPropertyChanged
        { 
             …
    
             public void NumberClicked(object sender, RoutedEventArgs e) //0-9
            {
                if (displayText == "0" || (operationClicked) || (calculated))
                    displayText = "";
    
                Windows.UI.Xaml.Controls.Button b = (Windows.UI.Xaml.Controls.Button)sender;
                displayText += b.Content;
                operationClicked = false;
                calculated = false;
            }
       }

    Notice the data context for the whole page is set to the static NFBManager. 

    This is a picture of the calculator (not very appealing yet).

    The two highlighted fields are textboxes which are bound as shown below.

    <StackPanel Grid.Row="0" Grid.RowSpan="5" Grid.Column="1" Margin="0,0,0,0">
                <StackPanel HorizontalAlignment="Right" Background="{StaticResource CalculatorBackground}" Margin="0,0,5,0">
                    <TextBlock Name="IntermediateTextBlock" Height="16" Width="320" Text="{Binding intermediateText}" HorizontalAlignment="Right" VerticalAlignment="Center"
                               FontWeight="ExtraLight" TextAlignment="Right" Margin="0,0,5,0" />
                </StackPanel>
                <StackPanel Background="{StaticResource CalculatorBackground}" Margin="0,0,5,0" HorizontalAlignment="Right">
                    <TextBlock Name="DisplayTextBlock" Height="75" Width="320" Text="{Binding displayText}" TextAlignment="Right" VerticalAlignment="Center"
                               FontSize="48" HorizontalAlignment="Right" Margin="0,0,5,0"/>
                </StackPanel>

    I'm having trouble figuring out how to x:Bind to the static class - which I wanted to do because that's where the binding for the displayText and intermediateText are as shown below here.

    public class ButtonManager : INotifyCollectionChanged, INotifyPropertyChanged
        {
          ...
         private string DisplayText { get; set; }
            public string displayText
            {
                get
                {
                    return DisplayText;
                }
                set
                {
                    DisplayText = value;
                    OnPropertyChanged("displayText");
                }
            }
    
            private string IntermediateText { get; set; }
            public string intermediateText
            {
                get
                {
                    return IntermediateText;
                }
                set
                {
                    IntermediateText = value;
                    OnPropertyChanged("intermediateText");
                }
            }
       }


    Honestly - the grey calculator and it's functions were supposed to be a whole separate model, however because I made the ButtonManager NFBManager a static class - I put the calculator class in that NFBManager static class... which I really don't want to do, however I don't know how to work with the two classes since I'm using binding for both. The blue buttons in the picture are bound to the NFBManager class - which has an observable collection that users can update in the settings page.

    For instance - the blue button bindings are here:

    <StackPanel Orientation="Horizontal" Margin="0,5,0,0">
                        <Button Name="Button1" Content="{Binding nfCollection[0].retailer}" Style="{StaticResource NFRegStyle1}" Margin="0,0,5,5" FontSize="12" Click="Website_Click" Visibility="{Binding nfCollection[0].visibility, Converter={StaticResource boolToVisibilityConverter}}"/>
                        <Button Name="Button2" Content="{Binding nfCollection[1].retailer}" Style="{StaticResource NFRegStyle1}" Margin="0,0,5,5" FontSize="12" Visibility="{Binding nfCollection[1].visibility, Converter={StaticResource boolToVisibilityConverter}}"/>
                        <Button Name="Button3" Style="{StaticResource NFRegStyle1}" Margin="0,0,5,5" FontSize="12" Visibility="{Binding nfCollection[2].visibility, Converter={StaticResource boolToVisibilityConverter}, UpdateSourceTrigger=PropertyChanged}">
                            <TextBlock Text="{Binding nfCollection[2].retailer}" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </Button>
                        <Button Name="Button4" Style="{StaticResource NFRegStyle1}" Margin="0,0,5,5" FontSize="12" Click="Website_Click" Visibility="{Binding nfCollection[3].visibility, Converter={StaticResource boolToVisibilityConverter}, UpdateSourceTrigger=PropertyChanged}">
                            <TextBlock Text="{Binding nfCollection[3].retailer}" TextWrapping="Wrap"/>
                        </Button>
                        <Button Name="Button5" Content="{Binding nfCollection[4].retailer}" Style="{StaticResource NFRegStyle1}" Margin="0,0,5,5" FontSize="12" Click="Website_Click" Visibility="{Binding nfCollection[4].visibility, Converter={StaticResource boolToVisibilityConverter}, UpdateSourceTrigger=PropertyChanged}"/>
                    </StackPanel>

    Again the data context is set to NFBManager - a static class which has the defn for the above observable collections and functions that update the collection.

    public class ButtonManager : INotifyCollectionChanged, INotifyPropertyChanged
        {
            #region Declarations
            ...
            
            private ObservableCollection<Button> NFCollection = new ObservableCollection<Button>();
            public ObservableCollection<Button> nfCollection
            {
                get
                {
                    return NFCollection;
                }
                set
                {
                    NFCollection = value;
                }
            }
            #endregion
            
           ...
           public void UpdateNFButtons()
            {
                var allButtons2 = new List<Button>();
                Handlers.Database db = new Handlers.Database();
                allButtons2 = db.ReturnAllRecords<Models.AddInCalculator.Button>(table, fieldname, ObjectPath);
    
                SortByRetailer(allButtons2);
    
                int i = 0;
                foreach(Button item in allButtons2)
                {
                    if(item.type == "Nonfood")
                    {
                        nfCollection.RemoveAt(i);
                        nfCollection.Insert(i, item);
                        ++i;
                    }
                }
            }
       }

    I included the UpdateNFButtons() function just as an example to show that the observablecollection for the blue buttons are updated from a local SQLite db.

    In conclusion: I'm having issues binding with x:Bind because I want the datacontext set to NFBManager so that the buttons can update in real time with the observablecollections. If any more details/clarification is needed - please ask. My design pattern is definitely not standard / optimal.



    Sunday, August 11, 2019 1:06 AM

Answers

  • Hi,

    You just could not bind static class or property using x:bind. Binding might be possible for static property binding. So I think you might still need to deal with the viewmodel. I have to say that I'm little confused about why you wants to using a static class. What I think is that you could put the calculator functions in a separate model (you've already know that), make the functions public for use. Then put the calculator class into the viewmodel and call the it when you need to calculate. 

    Like this:

        public class TestModel
        {
             
            // calculatorcore 
            public  calculatorCore calculatorManager { get; set; }
    
            //properties
            private string DisplayText { get; set; }
            public string displayText
            {
                get
                {
                    return DisplayText;
                }
                set
                {
                    DisplayText = value;
                    //OnPropertyChanged("displayText");
                }
            }
    
    
            private int result { get; set; }
            public int Result
            {
                get
                {
                    return result;
                }
                set
                {
                    result = value;
                    OnPropertyChanged("Result");
                }
            }
           ...other properties
           
    
            public TestModel()
            {
                calculatorManager = new calculatorCore();
                displayText = "test";
                .....
            }
    
    
            private void calculate(object sender, RoutedEventArgs e)
            {
                Result = calculatorManager.function1(1,1);
            }
    
            .....other functions
    
        }
    
    
        public class calculatorCore
        {
    
            public int function1(int first, int second) 
            {
               
            }
    
            public int function2(int first, int second)
            {
    
            }
        }
      public MainPage()
            {
                this.InitializeComponent();
                TestModel testmodel = new TestModel();
                DataContext = testmodel;
            }
    And now you could use x:bind for the button click event. Is this acceptable for you?

    Best regards,

    Roy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, August 12, 2019 7:28 AM
    Moderator

All replies

  • Hi,

    You just could not bind static class or property using x:bind. Binding might be possible for static property binding. So I think you might still need to deal with the viewmodel. I have to say that I'm little confused about why you wants to using a static class. What I think is that you could put the calculator functions in a separate model (you've already know that), make the functions public for use. Then put the calculator class into the viewmodel and call the it when you need to calculate. 

    Like this:

        public class TestModel
        {
             
            // calculatorcore 
            public  calculatorCore calculatorManager { get; set; }
    
            //properties
            private string DisplayText { get; set; }
            public string displayText
            {
                get
                {
                    return DisplayText;
                }
                set
                {
                    DisplayText = value;
                    //OnPropertyChanged("displayText");
                }
            }
    
    
            private int result { get; set; }
            public int Result
            {
                get
                {
                    return result;
                }
                set
                {
                    result = value;
                    OnPropertyChanged("Result");
                }
            }
           ...other properties
           
    
            public TestModel()
            {
                calculatorManager = new calculatorCore();
                displayText = "test";
                .....
            }
    
    
            private void calculate(object sender, RoutedEventArgs e)
            {
                Result = calculatorManager.function1(1,1);
            }
    
            .....other functions
    
        }
    
    
        public class calculatorCore
        {
    
            public int function1(int first, int second) 
            {
               
            }
    
            public int function2(int first, int second)
            {
    
            }
        }
      public MainPage()
            {
                this.InitializeComponent();
                TestModel testmodel = new TestModel();
                DataContext = testmodel;
            }
    And now you could use x:bind for the button click event. Is this acceptable for you?

    Best regards,

    Roy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, August 12, 2019 7:28 AM
    Moderator
  • Thanks for your help! Greatly appreciated.

    Monday, August 12, 2019 6:39 PM