This is my first foray into Hierarchical data and am having a bit of a problem.
In Silverlight 4, I am trying to get a list of isolated storage folders to display in a TreeView. Nothing displays at all. My Treeview is completely blank. What am I missing? I am getting data and it is correct.
Any help would be appreciated.
XAML
<sdk:TreeView x:Name="FolderTreeView" Grid.Column="0" Margin="0,0,3,0" ItemsSource="{Binding _Folders}">
<sdk:TreeView.ItemTemplate>
<sdk:HierarchicalDataTemplate ItemsSource="{Binding Path=Folders}">
<TextBlock Margin="0" Text="{Binding Name, Mode=OneWay}"/>
</sdk:HierarchicalDataTemplate>
</sdk:TreeView.ItemTemplate>
</sdk:TreeView>
CS
internal class Folder
{
public Folder() { Folders = new List<Folder>(); }
public string Name { get; set; }
public List<Folder> Folders { get; set; }
}
private List<Folder> _Folders = new List<Folder>();
public OpenFileDialog()
{
InitializeComponent();
ifs = IsolatedStorageFile.GetUserStoreForApplication();
var folder = new Folder
{
Name = "Root",
Folders = (from c in ifs.GetDirectoryNames()
select new Folder
{
Name = c,
Folders = LoadFolders(c)
}).ToList()
};
_Folders.Add(folder);
FolderTreeView.DataContext = new { _Folders };
}
private List<Folder>LoadFolders(string folderName)
{
if(folderName == null)
return null;
return (from c in ifs.GetDirectoryNames(folderName + "\\*.*")
select new Folder
{
Name = c,
Folders = LoadFolders(c)
}).ToList();
}
Thanks
A few things
<sdk:TreeView x:Name="FolderTreeView" Grid.Column="0" Margin="0,0,3,0"
ItemsSource="{Binding _Folders}">
you can't bind to private members.
You need to use ObservableCollections instead of Lists. The binding manager effectively listens for the CollectionChanged events fired by ObservableCollection and notifies the bound controls.
You'll want to implement INotifyPropertyChanged and raise PropertyChanged notifications in your property setters.
Finally, have you set the DataContext for the Treeview?
Also, look in your Output debug window for errors relating to binding.
Edit, ok try:
FolderTreeView.DataContext = this;
and wrap _Folders in a property
public ObservableCollection <Folder> Folders
{
get
{
return _Folders;
}
set
{
_Folders = value;
OnPropertyChanged("Folders");
}
}
change your binding to
<sdk:TreeView x:Name="FolderTreeView" Grid.Column="0" Margin="0,0,3,0"
ItemsSource="{Binding Folders}">
I've changed things quite a bit,
public class Folder : INotifyPropertyChanged
{
public Folder(string folderName)
{
Name = folderName;
Folders = new ObservableCollection<Folder>();
var _ifs = IsolatedStorageFile.GetUserStoreForApplication();
if (folderName != null)
{
Folders = new ObservableCollection<Folder>(
(from c in _ifs.GetDirectoryNames(folderName + "\\*.*")
select new Folder(folderName + "\\" + c)
));
}
else
{
Folders = new ObservableCollection<Folder>(
(from c in _ifs.GetDirectoryNames()
select new Folder(folderName + "\\" + c)
));
}
}
public string Name { get; set; }
private ObservableCollection<Folder> _Folders;
public ObservableCollection<Folder> Folders
{
get { return _Folders; }
set { _Folders = value; OnPropertyChanged("RootFolder"); }
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
public partial class OpenFileDialog : UserControl
{
public OpenFileDialog()
{
InitializeComponent();
RootFolder = new Folder (null);
RootFolders = new ObservableCollection<Folder>();
RootFolders.Add(RootFolder);
FolderTreeView.DataContext = this;
}
private Folder _RootFolder;
public Folder RootFolder
{
get { return _RootFolder; }
set { _RootFolder = value; }
}
private ObservableCollection<Folder> _RootFolders;
public ObservableCollection<Folder> RootFolders
{
get { return _RootFolders; }
set { _RootFolders = value; }
}
}
xaml
<sdk:TreeView x:Name="FolderTreeView" Margin="0,0,3,0" ItemsSource="{Binding RootFolders}">
<sdk:TreeView.ItemTemplate>
<sdk:HierarchicalDataTemplate ItemsSource="{Binding Path=Folders}">
<StackPanel>
<TextBlock Margin="0" Text="{Binding Name, Mode=OneWay}"/>
</StackPanel>
</sdk:HierarchicalDataTemplate>
</sdk:TreeView.ItemTemplate>
</sdk:TreeView>
Ok...problem solved. Don't understand why though.
I had the ChildWindow set as internal scope instead of public scope because I didn't want the window itself to be viewed external of my Silverlight class library. If anyone can answer why this would stop Hierarchical data binding but not standard data binding I would like to know.
Related
I am trying to get my head around Heirarchical DataTemplates and TreeViews in WPF and am having some trouble.
I have created an app with only a TreeView on the form as below and defined HierarchicalDataTemplate's for both a Directory object and a File object I then Bind the TreeView to the Directories property (ObservableCollection) of my model.
<Grid>
<Grid.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Directory}" ItemsSource ="{Binding Directories}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:File}" ItemsSource ="{Binding Files}">
<TextBlock Text="{Binding Path=FileName}"/>
</HierarchicalDataTemplate>
</Grid.Resources>
<TreeView Margin="12,12,0,12" Name="treeView1" HorizontalAlignment="Left" Width="204" >
<TreeViewItem ItemsSource="{Binding Directories}" Header="Folder Structure" />
</TreeView>
</Grid>
This works in that in the TreeView I see my directories and it recursively displays all sub directories, but what I want to see is Directories and Files! I've checked the model and it definately has files in some of the sub directories but I can't see them in the tree.
I'm not sure if it is my template that is the problem or my model so I have included them all! :-)
Thanks
OneShot
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private MainWindowViewModel _vm;
public MainWindowViewModel VM
{
set
{
_vm = value;
this.DataContext = _vm;
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var d = new Directory() { Name = "temp" };
recurseDir("c:\\temp", ref d);
VM = new MainWindowViewModel( new List<Directory>() { d } );
}
private void recurseDir(string path, ref Directory dir)
{
var files = System.IO.Directory.GetFiles(path);
var dirs = System.IO.Directory.GetDirectories(path);
dir.Name = path.Substring(path.LastIndexOf("\\")+1);
for (int i = 0; i < files.Length; i++)
{
var fi = new FileInfo(files[i]);
dir.Files.Add(new File() {
FileName = System.IO.Path.GetFileName(files[i]),
DirectoryPath = System.IO.Path.GetDirectoryName(files[i]),
Size = fi.Length,
Extension= System.IO.Path.GetExtension(files[i])
});
}
for (int i = 0; i < dirs.Length; i++)
{
var d = new Directory() { Name = dirs[i].Substring(dirs[i].LastIndexOf("\\")+1) };
recurseDir(dirs[i], ref d);
dir.Directories.Add(d);
}
}
}
-
public class MainWindowViewModel
: DependencyObject
{
public MainWindowViewModel(List<Directory> Dirs)
{
this.Directories = new ObservableCollection<Directory>( Dirs);
}
public ObservableCollection<Directory> Directories
{
get { return (ObservableCollection<Directory>)GetValue(DirectoriesProperty); }
set { SetValue(DirectoriesProperty, value); }
}
public static readonly DependencyProperty DirectoriesProperty =
DependencyProperty.Register("Directories", typeof(ObservableCollection<Directory>), typeof(MainWindowViewModel), new UIPropertyMetadata(null));
public Directory BaseDir
{
get { return (Directory)GetValue(BaseDirProperty); }
set { SetValue(BaseDirProperty, value); }
}
public static readonly DependencyProperty BaseDirProperty =
DependencyProperty.Register("BaseDir", typeof(Directory), typeof(MainWindowViewModel), new UIPropertyMetadata(null));
}
-
public class Directory
{
public Directory()
{
Files = new List<File>();
Directories = new List<Directory>();
}
public List<File> Files { get; private set; }
public List<Directory> Directories { get; private set; }
public string Name { get; set; }
public int FileCount
{
get
{
return Files.Count;
}
}
public int DirectoryCount
{
get
{
return Directories.Count;
}
}
public override string ToString()
{
return Name;
}
}
-
public class File
{
public string DirectoryPath { get; set; }
public string FileName { get; set; }
public string Extension { get; set; }
public double Size { get; set; }
public string FullPath
{
get
{
return System.IO.Path.Combine(DirectoryPath, FileName);
}
}
public override string ToString()
{
return FileName;
}
}
Take a look at this again:
<HierarchicalDataTemplate DataType="{x:Type local:Directory}" ItemsSource ="{Binding Directories}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:File}" ItemsSource ="{Binding Files}">
<TextBlock Text="{Binding Path=FileName}"/>
</HierarchicalDataTemplate>
What you're saying is that if you encounter an object of type File, display it with a text block and get its children from a property Files under the File. What you really want is for the Files to show up under each Directory, so you should create a new property that exposes both Directories and Files:
public class Directory
{
//...
public IEnumerable<Object> Members
{
get
{
foreach (var directory in Directories)
yield return directory;
foreach (var file in Files)
yield return file;
}
}
//...
}
and then your template becomes:
<HierarchicalDataTemplate DataType="{x:Type local:Directory}" ItemsSource ="{Binding Members}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:File}">
<TextBlock Text="{Binding Path=FileName}"/>
</DataTemplate>
UPDATE:
Actually, the above is not sufficient if you want to receive collection changed notifications for the Members. If that's the case, I recommend creating a new ObservableCollection and adding Directory and File entries to it in parallel to adding to the Files and Directories collections.
Alternately, you may wish to reconsider how you store your information and put everything in a single collection. The other lists are then simply filtered views of the main collection.
the idea here is that every revision of a file spawns a new file with a name that adds "_v1", "_v2", etc. The back end gets the files from disk and groups them based on that name. So a header might say "example", then when you click on the expander, you see "example", "example_v1", "example_v2", etc.
However, when this grouped data reaches the front-end, only the keys are showing, with an empty list of expanded content. Is my XAML messed up or is it something else?
This is MainPage.xaml:
<my:RadDataBoundListBox x:Name="listBox">
<my:RadDataBoundListBox.ItemTemplate>
<DataTemplate>
<my1:RadExpanderControl
Content="{ Binding }"
ExpandableContent="{ Binding }"
IsExpanded="True">
<my1:RadExpanderControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{ Binding Key }" />
</DataTemplate>
</my1:RadExpanderControl.ContentTemplate>
<my1:RadExpanderControl.ExpandableContentTemplate>
<DataTemplate>
<TextBlock Text="{ Binding Name }" />
</DataTemplate>
</my1:RadExpanderControl.ExpandableContentTemplate>
</my1:RadExpanderControl>
</DataTemplate>
</my:RadDataBoundListBox.ItemTemplate>
</my:RadDataBoundListBox>
This is from MainPage.xaml.cs:
public sealed partial class MainPage : Page
{
CollectionViewSource cvs = null;
public MainPage()
{
InitializeComponent();
cvs = new CollectionViewSource();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
cvs.Source = ViewModel.Files;
cvs.IsSourceGrouped = true;
listBox.ItemsSource = (IOrderedEnumerable<IGrouping<string, Files>>)cvs.Source;
}
}
This is from the ViewModel:
private IOrderedEnumerable<IGrouping<string, Files>> files;
public IOrderedEnumerable<IGrouping<string, Files>> Files
{
get
{
if (files == null)
{
var source = Source;
string[] separaters = { "_", "." };
files = from file in source
group file by file.Name.Split(separaters, StringSplitOptions.RemoveEmptyEntries)[0]
into g
orderby g.Key
select g;
}
return files;
}
}
This is how the list of filenames is pulled from disk:
public ObservableCollection<Files> Source
{
get
{
return GetFilesData(Folder).Result;
}
}
This is the model for the filenames:
public class Files
{
public string Name { get; set; }
}
I have a problem with my binding. Everything works except that the initial value displayed in the combo box of the selected is blank. The drop down has the two values below the blank that is originally display. Any help would be fantastic.
Main Class
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
public Data myData = new Data(new LocationSite("There", 9.81234));
Binding b = new Binding();
b.Source = MainWindow.Data.Location;
b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
b.Path = new PropertyPath("Gravity");
MainWindow.mainWindow.Gravity.SetBinding(TextBox.TextProperty, b);
Binding b = new Binding() { Source = MainWindow.Data.LocationSelection };
MainWindow.mainWindow.LocationComboBox.DisplayMemberPath = "Name";
MainWindow.mainWindow.LocationComboBox.SetBinding(ComboBox.ItemsSourceProperty, b);
//bind selection
MainWindow.mainWindow.LocationComboBox.DataContext = MainWindow.Data;
Binding selectedItemBinding = new Binding() { Source = MainWindow.Data, Path = new PropertyPath("Location"), Mode = BindingMode.TwoWay}
MainWindow.mainWindow.LocationComboBox.SetBinding(ComboBox.SelectedValueProperty, selectedItemBinding);
MainWindow.mainWindow.LocationComboBox.SelectedIndex = 0; // always index 0 but might need index 1 how do I make it use whatever location is?
}
}
Data class with a list of Locations and one location that is the selected. Somehow I need to tell the combo box that the one to select is the location that matched the list. Any Help????
public class Data : INotifyPropertyChanged
{
private LocationSite location;
private List<LocationSite> locationSelection;
public Location(LocationSite useLocation)
{
location = useLocation; // can either be "Here" or "There" need start index either 0 or 1
locationSelection = new List<LocationSite>();
locationSelection.Add(new LocationSite("Here", 9.795884));
locationSelection.Add(new LocationSite("There", 9.81234));
}
public LocationSite Location
{
get { return location; }
set {
if (location == null)
{
location = new LocationSite();
}
Location.Gravity = value.Gravity;
Location.Name = value.Name;
}
}
/// <summary>
/// Getter/Setter of a list of LocationSites
/// </summary>
public List<LocationSite> LocationSelection
{
get { return locationSelection; }
set { locationSelection = value; }
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(
this, new PropertyChangedEventArgs(propName));
}
}
The object that I have a list of
public class LocationSite : INotifyPropertyChanged
{
private string name;
private double gravity;
public LocationSite(string siteName, double siteGravity)
{
Name = siteName;
Gravity = siteGravity;
}
public string Name
{
get { return name; }
set { name = value;
this.OnPropertyChanged("Name");
}
}
public double Gravity
{
get { return gravity; }
set { gravity = value;
this.OnPropertyChanged("Gravity");
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(
this, new PropertyChangedEventArgs(propName));
}
}
}
The XAML file
<Window x:Class="Data.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Needs to be updated" Height="820" Width="1280" HorizontalAlignment="Left">
<Grid Name="MainScreenGrid">
<TextBox x:Name="Gravity" Grid.Column="8" HorizontalAlignment="Left" Height="23" Grid.Row="3" TextWrapping="NoWrap" Text="0.0" VerticalAlignment="Top" Width="140" IsHitTestVisible="False" IsReadOnly="True"/>
<ComboBox x:Name="LocationComboBox" Grid.Column="6" HorizontalAlignment="Left" Grid.Row="1" VerticalAlignment="Top" Width="140" Height="22"/>
</Grid>
</Window>
in your constructor try this
LocationComboBox.SelectedIndex = 0;
In your Data Class Try this
private LocationSite location;
public LocationSite Location
{
get
{
return location;
}
set
{
location=value;
OnPropertyChanged("Location")
}
}
And in MainWindowConstructor Set the Value Like This
MainWindow.Data.Location=MainWindow.Data.LocationSelection.FirstOrDefault();
In this method By default It will Take the First Item of LocationSelection as Location.
And You need to Use System.Linq NameSpace for FirstOrDefault().
Set the Location Value Before You Set the Binding.
I'm trying to write a C# WPF application and I'm stuck with the TreeView and ObservableCollection.
This is my TreeView Items.
| Root
--- SubItem
------ SubItem
| Root
--- SubItem
------ SubItem
---------- SubItem
I'm modifyng this items from other window and I need to update this treeview without re-loading all items. I've made my search and I found ObservableCollection. But I can't understand how to use ObservableCollection and notify changes and update this list.
Can you give me some sample code or help me with doing that?
Here is a good example to Implement Simplifying the WPF TreeView by Using the ViewModel Pattern.
This is just another sample,
Your Model:
public interface IFolder
{
string FullPath { get; }
string FolderLabel { get; }
ObservableCollection<IFolder> Folders { get; }
}
Your ViewModel:
class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
m_folders = new ObservableCollection<IFolder>();
//add Root items
Folders.Add(new Folder { FolderLabel = "Dummy1", FullPath = #"C:\dummy1" });
Folders.Add(new Folder { FolderLabel = "Dummy2", FullPath = #"C:\dummy2" });
Folders.Add(new Folder { FolderLabel = "Dummy3", FullPath = #"C:\dummy3" });
Folders.Add(new Folder { FolderLabel = "Dummy4", FullPath = #"C:\dummy4" });
//add sub items
Folders[0].Folders.Add(new Folder { FolderLabel = "Dummy11", FullPath = #"C:\dummy11" });
Folders[0].Folders.Add(new Folder { FolderLabel = "Dummy12", FullPath = #"C:\dummy12" });
Folders[0].Folders.Add(new Folder { FolderLabel = "Dummy13", FullPath = #"C:\dummy13" });
Folders[0].Folders.Add(new Folder { FolderLabel = "Dummy14", FullPath = #"C:\dummy14" });
}
public string TEST { get; set; }
private ObservableCollection<IFolder> m_folders;
public ObservableCollection<IFolder> Folders
{
get { return m_folders; }
set
{
m_folders = value;
NotifiyPropertyChanged("Folders");
}
}
void NotifiyPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
}
In xaml:
<TextBlock Text="Simple root binding" Foreground="Red" Margin="10,10,0,0" />
<TreeView ItemsSource="{Binding Folders}" Margin="10">
<TreeView.ItemTemplate>
<DataTemplate>
<TreeViewItem Header="{Binding FolderLabel}"/>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Full code
Okay so the problem is that my INotifyPropertyChanged isnt updting the list view n XAML
DiscoveredData.NetworkedComputersResults = NetworkedComputers; < this is where it loads the data into the DataContext and then calls the iproperty notify changed.
ListView_LocalComputers.ItemsSource = DiscoveredData.NetworkedComputersResults; < using this works fine and i can see all my data however this apparantly not the way to do it.
since i know that i can load the data into the list view using the ItemsSource im thinking the problem is in the XAML.
i would be greatful if someone could point me in the right direction.
Also if you see that i am doing this incorrectly please advise, im fairly new at this coding language and would like to do it the right way
Thank you in advance
<ListView Name="ListView_LocalComputers" ItemsSource="{Binding NetworkedComputerResults}">
<ListView.View>
<GridView>
<GridViewColumn Header="Status">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border CornerRadius="2,2,2,2" Width="20" Height="20" Background="Transparent" BorderBrush="Transparent" Margin="3,3,3,3">
<Image HorizontalAlignment="Left" VerticalAlignment="Center" Width="12" Height="12" Source="{Binding Image}" Stretch="Fill" Margin="2,2,2,2"/>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Local Computers" DisplayMemberBinding="{Binding ComputerName}">
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
//Constructor
public NetworkInformation()
{
InitializeComponent();
this.DataContext = DiscoveredData; //Defines the class to the view
Discovery();
}
//Method
public void Discovery()
{
GetIcon Icon = new GetIcon();
BitmapImage IconOfComputer = null;
List<DiscoveredComputer> NetworkedComputers = new List<DiscoveredComputer>();
DirectoryEntry Discover = new DirectoryEntry("WinNT://Workgroup");
BitmapImage On = Icon.LoadIcon(#"/Images/Icons/ComputerOn.ico");
BitmapImage Off = Icon.LoadIcon(#"/Images/Icons/ComputerOff.ico");
foreach (DirectoryEntry Node in Discover.Children)
{
try
{
if (Node.Properties.Count > 0)
{
IconOfComputer = On;
}
}
catch
{
IconOfComputer = Off;
}
if (Node.Name != "Schema") { NetworkedComputers.Add(new DiscoveredComputer { Image = IconOfComputer, ComputerName = Node.Name, MyToolTip = "Node Type = " + Node.SchemaEntry.Name }); }
}
DiscoveredData.NetworkedComputersResults = NetworkedComputers;
ListView_LocalComputers.ItemsSource = DiscoveredData.NetworkedComputersResults;
}
private class GetIcon
{
public BitmapImage IconStorage { get; set; }
public BitmapImage LoadIcon(String IconPath)
{
BitmapImage GeneratedIcon = new BitmapImage();
GeneratedIcon.BeginInit();
GeneratedIcon.UriSource = new Uri("pack://application:,,," + IconPath, UriKind.RelativeOrAbsolute);
GeneratedIcon.EndInit();
IconStorage = GeneratedIcon;
return GeneratedIcon;
}
}
public class NetworkData : INotifyPropertyChanged
{
#region Property Notify Standard for all classes
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
#endregion
#region Bound Data To View
private List<DiscoveredComputer> _NetworkedComputersResults;
public List<DiscoveredComputer> NetworkedComputersResults {
get { return _NetworkedComputersResults; }
set
{
_NetworkedComputersResults = value;
NotifyPropertyChanged("NetworkedComputersResults");
}
}
#endregion
public class DiscoveredComputer : NetworkData
{
public string ComputerName { get; set; }
public BitmapImage Image { get; set; }
public String MyToolTip { get; set; }
}
}
You should use ObservableCollection. It implements INotifyCollectionChanged which notifies when a collection changed, not just a single Item.
The items themselves should implement INotifyPropertyChanged of course...
You are binding a plain List<T> to your ListView. However this works fine, it will not fulfill the requirement of dynamic updating the list view when items are added / removed.
If you need the dynamic add/remove elements in your ListView simply use an ObservableCollection<T> instead of the List`.
private ObservableCollection<DiscoveredComputer> _NetworkedComputersResults;
public ObservableCollection<DiscoveredComputer> NetworkedComputersResults {
get { return _NetworkedComputersResults; }
set
{
_NetworkedComputersResults = value;
NotifyPropertyChanged("NetworkedComputersResults");
}
}
If all you need is elements be dynamically be added/removed, then the elements in the observable collection do not need to implement the INotifyPropertyChanged interface.
public class NetworkData
{
public NetworkData()
{
NetworkedComputersResults = new ObservableCollection<DiscoveredComputer>();
}
public ObservableCollection<DiscoveredComputer> NetworkedComputersResults{get;set;}
}
DiscoveryMethod
public void Discovery()
{
GetIcon Icon = new GetIcon();
BitmapImage IconOfComputer = null;
List<DiscoveredComputer> NetworkedComputers = new List<DiscoveredComputer>();
DirectoryEntry Discover = new DirectoryEntry("WinNT://Workgroup");
BitmapImage On = Icon.LoadIcon(#"/Images/Icons/ComputerOn.ico");
BitmapImage Off = Icon.LoadIcon(#"/Images/Icons/ComputerOff.ico");
foreach (DirectoryEntry Node in Discover.Children)
{
try
{
if (Node.Properties.Count > 0)
{
IconOfComputer = On;
}
}
catch
{
IconOfComputer = Off;
}
if (Node.Name != "Schema") { NetworkedComputers.Add(new DiscoveredComputer { Image = IconOfComputer, ComputerName = Node.Name, MyToolTip = "Node Type = " + Node.SchemaEntry.Name }); }
}
//Use Clear and Add .Dont assign new instance DiscoveredData.NetworkedComputersResults=new ....
DiscoveredData.NetworkedComputersResults.Clear();
foreach (var item in NetworkedComputers)
{
DiscoveredData.NetworkedComputersResults.Add(item);
}
}
I hope this will help.From my personal View it would be good If you create this Discovery method in ViewModel and would Call it from the Constructor of ViewModel . It seems two way communication like you setting property of ViewModel from View thats the job of Binding not code behind