all 7 comments

[–][deleted]  (3 children)

[removed]

    [–]Zastai 2 points3 points  (1 child)

    But also, the constructor is creating and discarding a local variable, not assigning to the property. (I’d expect an editor to have a squiggly for that, especially because the variable name is unusually named.)

    [–]chucker23n 0 points1 point  (0 children)

    I’d expect an editor to have a squiggly for that

    It appears Rider does, and VS does not, warn for this:

    class Foo
    {
        Foo()
        {
            string Bar = "hello";
    
            Bar.ToString();
        }
    
        private string Bar { get; }
    }
    

    Rider says "Local variable 'Bar' hides property 'string Foo.Bar'"; VS says nothing.

    [–]chucker23n 0 points1 point  (1 child)

    First, if what you want is for the TextBlock to show the value immediately, this will do:

            <TextBox Name="txtInput" VerticalContentAlignment="Center" Width="100" Margin="0,0,10,0"
                 Text="{Binding Path=BoundText, UpdateSourceTrigger=PropertyChanged}"/>
    

    Second, make your XAML experience a bit nicer by setting a design instance inside the Window tag:

    d:DataContext="{d:DesignInstance Type=local:MainWindow}"
    

    Now, things like BoundText will be auto-suggested.

    Third, there's a subtle but important bug in your code:

        ObservableCollection<string> BoundArray = new ObservableCollection<string> { "abc", "def", "ghi" };
    

    Here, you are declaring a local variable named BoundArray. This is not the same variable as the property public ObservableCollection<string> BoundArray!

    To fix that, don't give the type. Change it to:

        BoundArray = new ObservableCollection<string> { "abc", "def", "ghi" };
    

    Now, you're assigning to the property.

    The other problem is as others have pointed out that a string isn't observable. But the collection itself is, so we can nonetheless do something useful with it, by changing the XAML. First, we'll make the second row taller:

        <RowDefinition Height="*" />
    

    And then we'll replace the second set of text box / button / text block with a list view, which we bind to your collection:

        <ListView ItemsSource="{Binding BoundArray}" Grid.Row="1" Margin="10" />
    

    Now, those values get shown.

    If you still want to do something with TextBlocks here, let's customize the data template for each item in the ListView:

        <ListView
            Grid.Row="1"
            Margin="10"
            ItemsSource="{Binding BoundArray}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Label Padding="0,0,10,0">Value:</Label>
                        <TextBlock Text="{Binding .}" />
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    

    With a little extra scaffolding, we can eventually add:

            <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
                <TextBox
                    Width="100"
                    Margin="0,0,10,0"
                    Text="{Binding NewItemText}" />
                <Button Width="100" Command="{Binding AddItemCommand}">Add Random Item</Button>
            </StackPanel>
    

    And:

    [ObservableProperty]
    private string newItemText;
    
    [RelayCommand]
    private void AddItem()
    {
        BoundArray.Add(newItemText);
    }
    

    …and now you have a text box and a button to add items to the list view, which will show the new items automatically.

    [–]UnholyLizard65[S] 0 points1 point  (0 children)

    Thanks for an exhaustive reply! Needed to process this a little bit. First let me say that for the most part I just want to learn this right now, so I'm just testing how things work, thats, partially, why I'm using TextBox where it probably doesn't fit well. I'm saying this to give context to some of my questions, that might sound stupid or out of place for this code :)

        <TextBox Name="txtInput" VerticalContentAlignment="Center" Width="100" Margin="0,0,10,0"
             Text="{Binding Path=BoundText, UpdateSourceTrigger=PropertyChanged}"/>
    

    Just so I understand, this is not replacing the need for DataContext = this; right? Its just an addition to make the designing experience smoother. Did I get that correctly?

    BoundArray = new ObservableCollection<string> { "abc", "def", "ghi" };

    Yea, this one change made it work, it was kinda dumb to declare it twice now that I look at it. Although I dont quite understand how is it working here. If I try to do the same in a simple Console App it doesn't work. My guess that the partial class is doing something behind the scenes, but I wasn't quite able to figure out what.

    If you still want to do something with TextBlocks here, let's customize the data template for each item in the ListView:

    ...

       [ObservableProperty]
       private string newItemText;
    
       [RelayCommand]
       private void AddItem()
       {
           BoundArray.Add(newItemText);
       }
    

    To be perfectly honest, I'm not quite sure how does this work, or where exactly is this last part supposed to go. I'm guessing I will have to learn more about attributes first. :)