There is a XAML markup:

<ListBox x:Name="PathListView" Grid.RowSpan="2" Grid.ColumnSpan="1" Margin="5" ItemsSource="{Binding Path=SettingModel.CollectionPaths, Mode=Default}" /> 

So, in this case, the binding does not work - the displayed element is empty. But if you do this in the c # code and remove it from XAML - voila, everything works:

 PathListView.ItemsSource = ViewModel.MainViewModel.SettingModel.CollectionPaths; 

What is the difference between how to bind, in xaml or c # code?
Why does it work in one case and not in the other?

Both ObservableCollection <>

UPD .
Model code:

 using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.Serialization.Json; using System.Runtime.Serialization; namespace DocumentAdder.Model { [DataContract] public class SettingsModel : BaseModel { #region Fields private string _pathToDirectory; private string _fileTypes; private ObservableCollection<string> _collectionPaths; #endregion #region Properties /// <summary> /// Представляет собой путь к папке с файлами, которые следует обработать /// </summary> /// <value>PathToDirectory свойство задает/возвращает значение типа string поля, _pathToDirectory</value> [DataMember] public string PathToDirectory { get { return _pathToDirectory; } set { _pathToDirectory = value; NotifyPropertyChanged(); } } /// <summary> /// Предоставляет данные о типах текстовых файлов, которые необходимо сканировать и обрабатывать /// <value>FileTypes свойство возвращает значения типа string поля, _fileTypes</value> /// </summary> [DataMember] public string FileTypes { get { return _fileTypes; } private set { _fileTypes = value; NotifyPropertyChanged(); } } /// <summary> /// Возвращает коллекцию всех путей, с которых нужно обработать файлы /// </summary> /// <value>CollectionPaths свойство возвращает значение типа ObservableCollection<string> поля, _collectionPaths</value> [DataMember] public ObservableCollection<string> CollectionPaths { get { return _collectionPaths; } private set { _collectionPaths = value; NotifyPropertyChanged(); } } #endregion /// <summary> /// Создает модель настроек, /// инициализирует коллекцию путей к директориям, где лежат файлы, /// задает возможные форматы файлов для чтения. /// </summary> public SettingsModel() { _fileTypes = "*.txt, *.doc, *.docx, *.rtf, *.otd, *.pdf"; CollectionPaths = new ObservableCollection<string>(); } } } 

ViewModel Code:

 using DocumentAdder.Helpers; using DocumentAdder.Model; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; using Microsoft.WindowsAPICodePack.Dialogs; namespace DocumentAdder.ViewModel { public class MainViewModel { public MainModel DocumentAdderModel { get; private set; } public static SettingsModel SettingModel { get; set; } #region Commands //main programm commands public ICommand StartProgrammCommand { get; private set; } public ICommand StopProgrammCommand { get; private set; } public ICommand RestartProgrammCommand { get; private set; } //settings commands public ICommand AddLocalStorageCommand { get; private set; } #endregion #region Methods //main programm methods //settings methods private void addLocalStorage() { List<string> selectedPaths = null; var cofd = new CommonOpenFileDialog(); cofd.IsFolderPicker = true; //cofd.Title = ""; cofd.Multiselect = true; if (cofd.ShowDialog() == CommonFileDialogResult.Ok) { selectedPaths = cofd.FileNames.ToList<string>(); } if (selectedPaths != null) { foreach (var item in selectedPaths) { SettingModel.CollectionPaths.Add(item); } } } private void addFTPStorage() { } #endregion static MainViewModel() { if (SettingModel == null) { var single = new SettingsModel(); SettingModel = single; } } public MainViewModel() { DocumentAdderModel = new MainModel(); AddLocalStorageCommand = new DelegateCommand(arg => addLocalStorage()); } } } 

Window XAML code:

 <Window x:Class="DocumentAdder.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:PlatformUI="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.14.0" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:DocumentAdder" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="clr-namespace:DocumentAdder.ViewModel" Title="Document Adder" Width="535" Height="340" Closing="Window_Closing" mc:Ignorable="d"> <Window.DataContext> <vm:MainViewModel /> </Window.DataContext> <Grid> <TabControl x:Name="tabControl" Width="500" Height="282" Margin="10,10,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"> <TabItem Header="Стартовая"> <Grid Margin="0,0,0,2" Background="#FFE5E5E5"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <DataGrid x:Name="fileDataView" Grid.RowSpan="3" Grid.ColumnSpan="2" Width="474" Margin="10,10,0,38" HorizontalAlignment="Left"> <DataGrid.Columns> <DataGridTextColumn Width="40" CanUserResize="False" CanUserSort="True" Header="#" IsReadOnly="True" /> <DataGridTextColumn Width="200" CanUserResize="True" CanUserSort="False" Header="Путь к файлу" IsReadOnly="True" /> <DataGridTextColumn Header="Тип файла" /> <DataGridTextColumn Width="110" CanUserResize="False" CanUserSort="True" Header="Дата добавления" IsReadOnly="True" /> <DataGridCheckBoxColumn Header="В БД?" /> </DataGrid.Columns> </DataGrid> <Button x:Name="StartBtn" Grid.Row="2" Width="75" Margin="10,61,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Start" /> <Button x:Name="StopBtn" Grid.Row="2" Width="75" Margin="90,61,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Stop" /> <Button x:Name="RestartBtn" Grid.Row="2" Width="75" Margin="170,61,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="Restart" /> </Grid> </TabItem> <TabItem Header="Настройки"> <Grid Background="#FFE5E5E5"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="150" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <ListBox x:Name="PathListView" Grid.RowSpan="2" Grid.ColumnSpan="1" Margin="5" /> <StackPanel Grid.Row="0" Grid.Column="1"> <Button Height="28" Margin="10,10,10,0" Command="{Binding AddLocalStorageCommand}" Content="Добавить путь" /> </StackPanel> </Grid> </TabItem> <TabItem Header="О программе"> <TextBlock><Run Text="Добавление и фильтрация данных" /></TextBlock> </TabItem> </TabControl> </Grid> 

Whole project

  • And can you describe in more detail, in particular, the transitions between your UI, may not have time to update? - Yury Bakharev
  • show how you set the DataContext window where your ListBox is located - Gardes
  • @FoggyFinder DataContext is installed, the remaining bindings work. - Ep1demic
  • @YuryBakharev, and there are no other windows, there is a TabControl, on another tab this ListBox. Linking a command to a button works through xaml, but this is not. - Ep1demic
  • And what does Visual Studio write about binding errors in the Output window? There is often useful information. - VladD

1 answer 1

I tried to create a minimally reproducible example. Request to the author to correct, if I misunderstood the problem.

There is a non-static class with a non-static collection property:

 public class Model { public ObservableCollection<string> Collection { get; } public Model() { Collection = new ObservableCollection<string>(); } } 

There is a window view model in which this class appears as a static property and which can add elements to the collection:

 public class MainVm { private int currentItem; public static Model Model { get; } static MainVm() { if (Model == null) { Model = new Model(); } } public MainVm() { AddItemToCollectionCommand = new RelayCommand(() => Model.Collection.Add((++currentItem).ToString())); } public ICommand AddItemToCollectionCommand { get; } } 

There is a view that should show the list of elements of the collection in the ListBox:

 <Window ...> <Window.DataContext> <local:MainVm/> </Window.DataContext> <StackPanel> <Button Command="{Binding AddItemToCollectionCommand}" Content="Add"/> <ListBox ItemsSource="{Binding Collection, Source={x:Static local:MainVm.Model}}"/> </StackPanel> </Window> 

If you organize the binding in this way, the code will work.

UPD

@ Ep1demic, firstly, the binding is not Collection , but CollectionPaths . Secondly, the problem is that you reinstall the value of a static property. Those. it turns out the following:

  1. Created a class MainViewModel .
  2. Worked Binding to SettingModel.CollectionPaths (i.e., to the value created in the static constructor).
  3. The value of the SettingModel property SettingModel changed.

As a result, the binding works, but to an empty collection. So you need to come up with something. Either find a way to notify the external code of a static property change, or get rid of static, or not change the value of the property.

  • It should, but it does not work;) Well, I don’t know. Threw the project on the yadisk, if someone wants to - dig. - Ep1demic
  • @ Ep1demic, updated the answer - Vlad