Properly binding list ItemsSource to Linq Table - linq

I'm trying to bind a list box's items source to a Linq Table, the same way you would usually bind a ObservableCollection to it.
I want my list to update with the table when items are removed, added and changed.
I've implemented the INotifyPropertyChanged on the classes of which the table consists. This makes the list update the properties that my items contain, however, in order to update the list when items are added or removed, I have to programmatically rebind the ItemsSource in order to forcefully update the list.
Data context
public class LocalDatabase : DataContext
{
public static string connectionString = "Data Source=isostore:/Database.sdf";
public LocalDatabase() : base(connectionString) { }
public Table<Connection> Connections;
}
Table objects
[Table]
public class Connection : INotifyPropertyChanged
{
private string name;
private string ip;
private ushort port;
[Column(IsPrimaryKey=true, IsDbGenerated=true)]
public int ID { get; set; }
[Column]
public string Name { get { return name; } set { name = value; NotifyPropertyChanged("Name"); } }
[Column]
public string IP { get { return ip; } set { ip = value; NotifyPropertyChanged("IP"); } }
[Column]
public ushort Port { get { return port; } set { port = value; NotifyPropertyChanged("Port"); } }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Target list
<ListBox Name="listBoxConnections" SelectionChanged="listBoxConnections_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432" Height="78">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="Edit" Click="ConnectionEdit" Tag="{Binding ID}" />
<toolkit:MenuItem Header="Delete" Click="ConnectionDelete" Tag="{Binding ID}" />
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<StackPanel Orientation="Horizontal" Margin="12,-6,12,0">
<TextBlock Text="{Binding IP}" Style="{StaticResource PhoneTextSubtleStyle}" Margin="0" />
<TextBlock Text=":" Margin="2,0,2,0" />
<TextBlock Text="{Binding Port}" Style="{StaticResource PhoneTextSubtleStyle}" Margin="0" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Current binding method
public LocalDatabase Database { get; set; }
public MainPage()
{
InitializeComponent();
Database = new LocalDatabase();
if (!Database.DatabaseExists()) Database.CreateDatabase();
listBoxConnections.ItemsSource = Database.Connections;
DataContext = this;
}
I'm afraid there might be a duplicate somewhere, but I've been searching for the last 2 days, and found no solution or similar question. Probably using the wrong queries.
So, in summary, I want to know the correct way to bind a Table to a list, with it updating upon item removal or addition, and all of that good stuff.
I'm working with Windows Phone 7.1

The best way is to separate your UI code from your DB code. Let your ListBox bind to an ObservableCollection, instead of a Table.
Try reading this:
http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207023%28v=vs.105%29.aspx

Related

TreeView Binding List<String>

I can't seem to figure out how to get the TreeView to display a List
I checked SO, but can't sem to find the same scenario the leafs always seem to be objects and not simple strings.
I can't figure out the correct combination of HierarchicalDataTemplate and DataTemplate to get it to work. Using the following Object. The binding happens I just only see the first level and not the leaves.
public class Trunk
{
public Trunk(string tn)
{
TrunkName = tn;
Branches = new List<Branch>();
}
public List<Branch> Branches { get; set; }
public string TrunkName { get; set; }
}
public class Branch
{
public Branch(string bn)
{
BranchName = bn;
Leaves = new List<string>();
}
public List<string> Leaves { get; set; }
public string BranchName { get; set; }
}
Tree = new Trunk("Root")
{
Branches =
{
new Branch("Branch1"){Leaves = {"Leaf1","Leaf2"}},
new Branch("Branch2"){Leaves = {"Leaf3","Leaf4"}}
}
};
And the following Template
<TreeView ItemsSource="{Binding Trees}" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Branches}">
<TextBlock Text="{Binding Path=TrunkName}" />
<HierarchicalDataTemplate.ItemTemplate >
<DataTemplate>
<TextBlock Text="{Binding BranchName}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
EDIT:
Of course after spending days trying to figure out what wasn't clicking. I figured it out after posting for help.
PS the TreeView ItemsSource is set from the ViewModel bound to the Window DataContext.
<TreeView ItemsSource="{Binding Trees}" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Branches}">
<TextBlock Text="{Binding Path=TrunkName}" />
<HierarchicalDataTemplate.ItemTemplate >
<HierarchicalDataTemplate ItemsSource="{Binding Leaves}">
<TextBlock Text="{Binding BranchName}"/>
<HierarchicalDataTemplate.ItemTemplate >
<DataTemplate>
<TextBlock Text="{Binding }"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

Listbox items won't update with binding wp7

I have a listbox, with custom items. Code:
<ListBox Height="600" HorizontalAlignment="Left" Margin="7,6,0,0" Name="friendList" VerticalAlignment="Top" Width="449" ItemsSource="{Binding Friends}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5,0">
<Image Height="120" HorizontalAlignment="Left" Name="image" Stretch="Fill" VerticalAlignment="Top" Width="120" Source="{Binding ImageUri}" GotFocus="image_GotFocus"/>
<CheckBox Height="78" HorizontalAlignment="Left" Margin="65,63,0,0" x:Name="selectedChckbox" VerticalAlignment="Top" Width="55" IsChecked="{Binding Selected, Mode=TwoWay}"/>
<TextBlock Height="58" HorizontalAlignment="Left" Margin="0,122,0,0" x:Name="nameTextBlck" VerticalAlignment="Top" Text ="{Binding Title}" Width="120" TextWrapping="Wrap" GotFocus="name_GotFocus"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I've created a veiwmodel for the values for binding, and when I click on one item I want to change the checkbox state like so:
friendSelectionViewModel.Friends[_selectFriendContent.friendList.SelectedIndex].Selected = !friendSelectionViewModel.Friends[_selectFriendContent.friendList.SelectedIndex].Selected;
The ViewModel Code:
public class FacebookFriendSelectionViewModel : INotifyPropertyChanged
{
public FacebookFriendSelectionViewModel()
{
Friends = new ObservableCollection<TempFriends>();
}
/// <summary>
/// A collection for MenuItemViewModel objects.
/// </summary>
public ObservableCollection<TempFriends> Friends { get; private set; }
public void AddItem(TempFriends item)
{
Friends.Add(item);
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
public class TempFriends
{
bool _selected;
public string Title { get; set; }
public string ImageUri { get; set; }
public bool Selected {
get
{
return _selected;
}
set
{
_selected = value;
OnPropertyChanged("Selected");
}
}
public string Id { get; set; }
public TempFriends(string title, string imageUir, bool selected, string id)
{
Title = title;
ImageUri = imageUir;
_selected = Selected = selected;
Id = id;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
But the only way the listbox gets the values updated, if I set the datacontext to null and than assign the viewmodel aggain like so:
_selectFriendContent.DataContext = null;
_selectFriendContent.DataContext = friendSelectionViewModel;
But this takes about 5-10 seconds to refresh the list. I know there is a better solution, I just cant figure out how.
Thanks in advance!
TempFriends class doesn't implement INotifyPropertyChanged as far as I see. Just add public class TempFriends : INotifyPropertyChanged

ObservableCollection not updating the listview

I have an ObservableCollection which is viewed in a custom listbox. I need the listbox to update the view according to changes applied, like inserting new feeds or removing feeds from the ObservableCollection
parts of code are available below
public class lbl
{
public ObservableCollection<feed> ModifiedItems
= new ObservableCollection<feed>();
public lbl()
{
InitializeComponent();
listBox1.ItemsSource = ModifiedItems ;
}
public void update(object sender, EventArgs e)
{
var x = ModifiedItems.Last();
listBox1.Items.Add(x);
}
}
public class feed
{
public int ID { get; set; }
public int source_id { get; set; }
public string title { get; set; }
public string source_icon { get; set; }
public string url { get; set; }
public string pudate { get; set; }
}
XAML
<ListBox x:Name="listBox1" >
<ListBox.ItemTemplate >
<DataTemplate >
<StackPanel Width="400" Margin="20" >
<Button x:Name="pic" Tag="{Binding Id}">
<Button.Template>
<ControlTemplate>
<TextBlock Text="{Binding title}" TextWrapping="Wrap" FontFamily="Arial" FontSize="28" Tag="{Binding Id}"/>
</ControlTemplate>
</Button.Template>
</Button>
<TextBlock Text="{Binding pudate}" TextWrapping="Wrap" FontSize="24"/>
<Image Source="{Binding source_icon}" Width="100" Height="60"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Note: This is not part of the code.
It gives me the error when trying to add an Item "Operation not supported on read-only collection."
I tried the solution posted here Implementing CollectionChanged and still I get the same error.
Any help please, Thanks in advance
The problem is with your update method:
public void update(object sender, EventArgs e)
{
var x = ModifiedItems.Last();
listBox1.Items.Add(x);
}
The ItemsSource of your ListBox is set to the ModifiedItems which is an ObservableCollection. Therefore if you add or remove items from this collection, the ListBox UI will update automatically. For example, to add a new items to your view simply do the following:
ModifiedItems.Add(new feed());
This is the whole point of an ObservableCollection, the view can observe it!
If, rather than adding / removing items, you are updating existing items, you will need to make feed implement INotifyPropertyChanged.
Since you're setting the ItemsSource of the ListBox, you're binding the ModifiedItems collection to it.
This means you have to modify ModifiedItems, and not the ListBox to add/remove items, which then will update accordingly.
public void update(object sender, EventArgs e)
{
var x = ModifiedItems.Last();
ModifiedItems.Items.Add(x);
}
Why you want to duplicate the last item is beyond me. But that's the change you need to do.

how to populate values to list box from a string array

I have a string array and i need to populate its value to a list box.but the values are not get in the list box. here is my code
xaml
'<ListBox Name="listBox_1" Background="White" Margin="3,131,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,1,0,0" BorderBrush="#FFC1BCBC" Width="480">
<Grid Height="80">
<TextBlock Name="list"
Text="{Binding Path=Names}"
FontSize="36"
TextWrapping="Wrap"
Foreground="Black" FontWeight="Normal"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>'
class
'public class Names
{
//Model Class to hold Category details
public string Title { get; set; }
public string[] Names { get; set; }
public string[] Value { get; set; }
}'
xaml.cs
'protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
string[] name = ((Application.Current as App).obj_category.Names);
listBox_1.ItemsSource=name;
}'
i didnt get the names displayed in the list box.but i got the border lines that is, if the string contain 3 names i got three blank rows.why the text in it doesnot display?could any one help me .
DataContext in your ListBox is of type string[] and DataContext in each DataTemplate is a string which doesn't have a property Name.
Change Text="{Binding Path=Name}" to Text="{Binding}".

WP7/Silverlight How do you toggle a checkbox inside a list?

I'm having issues trying to figure this out. Basically, I have a listbox with a checkbox in it, making it a "Checked" listbox.
What I want to do is when a user hits a button, the checkbox is toggled (either shows or hides).
I've tried binding the visibility to a property in my view model but that isn't work.
What is the correct way to go about this? I've searched google and SO and couldn't find anything solid.
Thanks.
Bind visibility of the checkbox to a property of the class contained in the list that is the items source of the listbox.
Here is some code. This was a quick test and uses code behind but should be easily ported to your view model.
Class:
public class CheckString
{
public Visibility Visibility
{
get
{
Visibility retval = Visibility.Collapsed;
if (IsChecked)
{
retval = Visibility.Visible;
}
return retval;
}
}
public bool IsChecked { get; set; }
public string Description { get; set; }
public CheckString() {}
}
Code behind
public partial class MainPage : PhoneApplicationPage
{
public List<CheckString> CheckStringList { get; set; }
// Constructor
public MainPage()
{
InitializeComponent();
SetupList();
DataContext = this;
}
private void SetupList()
{
CheckStringList = new List<CheckString>();
CheckString cs1 = new CheckString { Description = "Test 1"};
CheckStringList.Add(cs1);
CheckString cs2 = new CheckString { IsChecked = true, Description = "Test 2" };
CheckStringList.Add(cs2);
CheckString cs3 = new CheckString { Description = "Test 3" };
CheckStringList.Add(cs3);
}
}
Xaml
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="Auto" />
<ColumnDefinition
Width="*" />
</Grid.ColumnDefinitions>
<CheckBox
Grid.Column="0"
Visibility="{Binding Visibility}"
IsChecked="{Binding IsChecked}" />
<TextBlock
Grid.Column="1"
Text="{Binding Description}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Resources