0

I came from a Linux heavy environment, where I wrote most of my tools in Python but now I am in a windows heavy environment, and need to share my tools with my team and some need to be GUI driven so I am trying to learn C#/WPF. I'm getting confused on Data Binding to an ObservableCollection in the code behind. I can get it work, but I don't understand why, which bothers me.

My code is simple, and I am literally just trying to get the basics working so I can move on to more complicated parts:

XAML:

<ListView x:Name="lvUrlList" HorizontalAlignment="Left" Height="441" Margin="15,62,0,0" VerticalAlignment="Top" Width="486" SelectionChanged="listView_SelectionChanged" ItemsSource="{Binding Path=urlList, ElementName=MainWindow1}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <WrapPanel>
                    <TextBlock Text="{Binding domain}"/>
                </WrapPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

Code Behind:

namespace ReferalScraper
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        //public ObservableCollection<Url> urlList { get; set; } // Method 1
        public ObservableCollection<Url> urlList = new ObservableCollection<Url>(); // Method 2
        public MainWindow()
        {
            // urlList = new ObservableCollection<Url>(); // Method 1
            InitializeComponent();
            urlList.Add(new Url() { domain = "www.test1.com" });

        }

        public class Url
        {
            public string domain { get; set; }

        }

        private void button_Click(object sender, RoutedEventArgs e)
        {

            urlList.Add(new Url() { domain = "www.test2.com" });
            urlList.Add(new Url() { domain = "www.test3.com" });

        }
    }
}

The uncommented method for creating and instantiating the ObservableCollection doesn't work, the code compiles but I get the output error:

System.Windows.Data Error: 40 : BindingExpression path error: 'urlList' property not found on 'object' ''MainWindow' (Name='MainWindow1')'. BindingExpression:Path=urlList; DataItem='MainWindow' (Name='MainWindow1'); target element is 'ListView' (Name='lvUrlList'); target property is 'ItemsSource' (type 'IEnumerable')

Which I understand that it means it can't find the urlList object in MainWindow. But I don't understand why it can't find it.

If I switch to the Method 1 and uncomment the following two lines (and comment out the "Method 2" part) it works fine:

public ObservableCollection<Url> urlList { get; set; }
...
public MainWindow(){
       urlList = new ObservableCollection<Url>()

Why is declaring the ObserverableCollection with the { get; set } needed? I don't quite grasp why I can't just instantiate my ObservableCollection as an empty ObserverableCollection like I am in Method 2.

I'm feeling incredibly dense, and haven't quite been able to track down the right terminology to even get close to answering my questions. Can anyone explain to a not so bright fellow what I am missing?

I have a feeling this is some C# understanding that I am missing.

2 Answers 2

4

The { get; set; } syntax defines your uriList as a property (an auto-implemented property, in this case ). Without this, uriList is simply a field.

WPF Data Binding cannot bind to fields. See this related question for some further discussion as to why this is the case.

Generally in C# fields are not usually exposed as public, properties are preferred. This allows you to change the get/set implementation if required. As an aside, the naming convention for properties is PascalCased (so UriList rather than uriList).

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you, I will take this and do more reading on Fields v. Properties, I have a feeling that is where I am missing some knowledge. Can I define and instantiate the property all at once? Is there a reason I need to later call the new ObserverableCollection<Url> part?
See the link to auto-implemented properties. If you are using C# 6 (if you are running VS 2015, you will be) then you can do this in one line similarly to field initialisation. You could also omit the set.
Oh boy, I was being extremely dense, and it just dawned on me. MainWindow is the class I am exposing the property on, so of course there is nothing there if nothing is exposed! That was a massive duh moment. Thank you again, the resources clarified it and I have some good reading to do.
0

You use ElementName binding when you try to get the Property you are binding, from another FramworkElement's property, which isn't the case here,

you need to first: properly set the DataContext either from the codebehind in the MainWindow constructor:

this.DataContext=this;

or from the Xaml in the Window

DataContext="{Binding RelativeSource={RelativeSource Self}}"

Then declare you UriList as a Property so it can be used with binding

 private ObservableCollection<Url> _uriList = new ObservableCollection<Url()
    {
        new Url() { domain = "www.test2.com" }
    };

    public bool UrlList
    {
        get
        {
            return _uriList;
        }

        set
        {
            if (_uriList == value)
            {
                return;
            }

            _uriList = value;

        }
    }

and change your binding to the following :

ItemsSource="{Binding UrlList}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.