I have what I believe should be simple two-way databinding in WPF setup, but the listbox (target) is not updating as the collection changes.
I'm setting this ItemsSource of the ListBox programmatically:
lstVariable_Selected.ItemsSource = m_VariableList;
And the ListBox is declared as follows:
<ListBox Margin="5" Name="lstVariable_Selected">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="1" Margin="0">
<TextBlock FontSize="25" Text="{Binding Path=Name}" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When I initially set the ItemsSource, the ListBox (which is not visible at the time) gets its items set. However, if I go view the ListBox, updates seem to stop at that point.
I can then remove an item from the m_VariableList collection, and it does not disappear from the ListBox. Likewise, if I add one, it doesn't appear.
What gives?
Is your m_VariableList implementing INotifyCollectionChanged? If it's not an ObservableCollection, then changes to it's contents will not automatically be reflected in the UI.
The problem is not in the XAML that you have provided. I used the same XAML successfully in a test application; however, I was able to replicate the issue you are experiencing by re-instantiating the m_VariableList variable.
When the m_VariableList is given a new instance, or pointed to a new object, it is not reflected in the ListBox because the control has its own reference to the data. This may not be the cause of your problem, but I'd recommend looking over your code-behind to ensure that the variable is not getting re-instantiated.
i got stuck for more than hour and then simple logic solved this problem
just set itemsource to clear list and then set source u need again
lstVariable_Selected.ItemsSource = new List<Object>();
lstVariable_Selected.ItemsSource = m_VariableList;
Related
I'm trying to figure out how to print a ListView ItemTemplate using the uwp PrintHelper.cs sample. Everything works, except the print preview does not display items added to the ListView at runtime. I can add other controls such as a textbox, and the print preview will show it, so there must be something peculiar with printing databound ListView items at runtime, but I cannot find any information about it.
<ListView x:Name="ClipboardList"
xmlns:m="using:QuickieEdit.Models"
ItemsSource="{x:Bind ViewModel.MemoryItems}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="m:MemoryItem">
<StackPanel Orientation="Horizontal">
<Button x:Name="MemoryCopyBtn"
Content="Copy"
Click="How to Copy currently selected
MemoryListItem.Text?"/>
<TextBox x:Name="MemoryListItem"
Text="{x:Bind Memory, Mode=TwoWay}">
</TextBox>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
I cannot understand your exact query, but I think you may be facing situation where your ListView does not get updated with the model and hence does not show up while printing. You can use
ObservableCollection<Model> instead of List<Model>
This will solve your problem or if it does not please provide the c# code in detail as well
Cheers
below is the wp app code in xaml. code loads number of images and its name. Now i want to get the currently tapped image's url and name to be passed as parameters into another page to load that particular imgae and name. help me.
<ListBox Name="tileList" Grid.Row="2" Margin="12,0,14,0" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock Text="{Binding TileName}"></TextBlock>
<Image Source="{Binding ImgUri}" Height="200" Width="350" Margin="5,0,0,0" Tap="on_Tap">
</Image>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This is really basic thing that you should figure out by yourself. But I give theory here not code.
Look for ListBox selection changed event. and then from this
typecast the sender as ListBox and from this get the SelctedItem.
This selected Item will be type of ItemClass of your List is made of
say - List that you have set as Itemsource of Listbox.
As till now you got the Selected ItemClass object that will
contain TileName and ImageUri. So use the MVVM Messenger Class to
send this item to next page. You can google it how use MVVM
messenger you wil find the Answer.
I can give you the code but I think in starting phase you should try lots of thing by yourself. happy learning :)
Edit 1:-
Hi The way You send the parameter from one page to another is correct. Here is the screenshot.
Source Page-navigation with parameters
Can you tell me what is not working ? are you getting any exception ?
Any question just comment.
#loop im getting tilename and imguri in variable name by using the following code
ListBox lb = (ListBox)sender;
var name = lb.SelectedItem;
NavigationService.Navigate(new Uri("/Options.xaml?name=" + name, UriKind.Relative));
help me to get the tilename and imguri values from variable name.
I have a TreeView that I am binding to an ItemsSource that creates a CheckBox for each item. Here is the xaml:
<TreeView x:Name="ReasonTreeView" Height="Auto" Background="Transparent"
BorderThickness="0" IsTabStop="False"
ItemsSource="{Binding Path=AnswerOptions}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type QSB:Answer}" ItemsSource="{Binding Path=AnswerOptions}">
<StackPanel Orientation="Horizontal">
<CheckBox Margin="0,5"
IsChecked="{Binding Path=IsSelected}"
IsEnabled="{Binding Path=Value,
Converter={StaticResource ReasonValueToEnabledConverter}}"
Visibility="{Binding Path=AnswerOptions,
Converter={StaticResource ParentNodeVisConverter}}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
In my application I then create multiple instances of these. Depending on the instance of the TreeView, certain CheckBoxes need to be disabled so the user can not select them, however I'm uncertain of how I can access the individual items in the HierarchicalDataTemplate in the code.
After looking around for a while the only thing I can think of is to build the whole TreeView in the code behind instead of the xaml, but I would rather not have to resort to that. Is there anything else that I can do?
To help clarify my point and for illustrative purposes, this is essentially what I want to be able to do (in pseudocode): ReasonTreeView.ItemsSource[5].IsEnabled = false;
Which would disable the CheckBox (and any other controls in that HierarchicalDataTemplateItem) at index 5 of the TreeView's ItemsSource
Let me know if more information is needed
I meant that binding on the checkbox's isenabled property Path=Value. That Value member has to be bool and implement INotifyPropertyChanged then you can control IsEnabled from your model. Dont forget to add Mode=Twoway to your binding
Instead of accessing the CheckBox through Control.ItemsSource property you should make the change in your underlying collection (that is itemssource of your control). After making the change notify the View (your Control) that data has been changed so update the control.
Implement INotifyPropertyChanged in your underlying class and after changing the Property (which is responsible for Enabled/Disabled) value Notify the View.
If you are not familiar with concepts of Data Binding and INotifyPropertyChanged, I would suggest you to read some basic tutorials about it. It is one of the major feature of WPF which makes life very easy for doing things like yours
My program needs to take input from a fire alarm panel over a serial connection and populate a list based on it. When a new device is reported from the panel, the statement is parsed and the device is added to the device List.
That part of my program all works fine and dandy. The problem now is displaying the list of fire alarm devices to the user.
I am hoping to do this using a DataGrid (unless there's a better way?) but am not able to find a lot of helpful documentation on WPF DataGrids that is relevant to me. Most of what's out there seems to be displaying data from a database. Mine however, needs to update every time the panel spits out a new device description and the device List in my program is appended.
I see I can set AutoGenerateColumns to true and initially display my list just fine. BUT, I would like to customize the column headers. Also this doesn't update when the List is appended so I'm not sure how to "refresh" it.
When AutoGenerateColumns is false, I get no data displayed. When the program runs it shows me the correct number of rows corresponding to the number of items in my list, but no data. Wondering how/if I need to link each column with its corresponding device data member?
Lastly, how do you format a DataGrid to look pretty through re-sizes? I can set column width and all that, but what I want is a few of the columns to be fixed width, and the middle column to expand to fill remaining available area.
This is my first stab at WPF. Any help would be greatly appreciated!
Personaly i dont like DataGrid much. Yes they are easier to bind and they offer built-in resize and sorting options but they are not as flexible as an ItemsControl with a good DataTemplating on your Objects. Let me explain myself.
I tend to populate my ItemsControl with an ObservableCollection. Then, i use a DataTemplate in order to tell my ItemsControl how to display my custom items.
Your CustomObjects can be Modeles objects if your doing MVVM.
If your list is binded to an ObservableCollection, the Added and Removed items will appear dynamicly into your list, which is what i belive your trying to do.
For the column size, you could put a Grid specifying GridColumns width to fixed Width for some columns and * for others so they fill the remaining space.
Here's an alternative to the GridView
I use a ScrollViewer around my ItemControl so if the ItemsControl get too big, you can scroll it.
The ItemsControl's ItemSource is binded to your FireAlarms's ObservableCollection.
The WrapPanel in the ItemsControl will contain each DataTemplate. It's Width is binded to his parent (or ancestor if you will) which is an ItemsControl
<ScrollViewer
Grid.Row="x"
Grid.Column="y"
VerticalScrollBarVisibility="Auto"
Margin="5">
<ItemsControl
BorderBrush="DarkBlue"
BorderThickness="2"
ItemsSource="{Binding Path=FireAlarms}"
ItemTemplate="{StaticResource FireAlarmsTemplate}"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel
Orientation="Horizontal"
Width="{Binding RelativeSource=
{RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}},
Path=ActualWidth}"
>
</WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
Ok then you need a DataTemplate. You can put the DataTemplate in your windows's ressource or in a DataDictionnary. Lets say you have a class :
FireAlarm
{
Public String AlarmInfo1;
Public String AlarmInfo2;
Public String AlarmInfo3;
}
Here could be a nice DataTemplate to start with :
<DataTemplate x:Key="FireAlarms">
<Border
BorderBrush="SteelBlue"
Background="LightBlue"
BorderThickness="2"
Margin="10"
Padding="10">
<StackPanel
Orientation="Vertical"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="5"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label
Grid.ColumnSpan="3"
Grid.Row="0"
Content="{Binding Path=AlarmName}"
Margin="5,-5,5,10"
FontWeight="Bold"
FontSize="16"
HorizontalContentAlignment="Center"
HorizontalAlignment="Center">
</Label>
<TextBlock
Text="Alarm information 1" Grid.Row="1" Grid.Column="0" />
<TextBox
Text="{Binding Path=AlarmInfo1}"
Grid.Column="2"
Grid.Row="1"
>
</TextBox>
<TextBlock
Text="Alarm information 2" Grid.Row="2" Grid.Column="0" />
<TextBox
Text="{Binding Path=AlarmInfo2}"
Grid.Column="2"
Grid.Row="2"
>
</TextBox>
<TextBlock
Text="Alarm information 3" Grid.Row="3" Grid.Column="0" />
<TextBox
Text="{Binding Path=AlarmInfo3}"
Grid.Column="2"
Grid.Row="3"
>
</TextBox>
</Grid>
</StackPanel>
</Border>
</DataTemplate>
Ok I hope this is usefull for you. My Template will generate 1 square per alarm. If you'd rather have it in a Table like a GridView, you could modify this using a verticaly oriented stack panel and use a grid with variable // invariable column width but since you asked for anything usefull, i tough i'd guive you something fun to work with!
Enjoy!
Some time back I wrote a post Create DataGrid in WPF using code take a look at it, it will help you in creating data grid in dynamic scenarios like yours
If you a dynamic grid (meaning the number and design of the columns are unknown at design time), I do it with code-behind with binding. I generally use the MVVM pattern (if you not familiar with this, I really recommend reading into it since it is THE pattern when working with WPF).
1) You have to set Auto-Generate columns to false of course and give grid a name (here myDataGrid)
GridViewDataColumn newColumn= new GridViewDataColumn();
myDataGrid.Columns.Add(newColumn)
This will add the column to your grid. Now the column will be empty. Now it depends on your data how to fill it with data. If you bind to a known property on the items, do:
newColumn.Binding = new Binding("knownPropertyName");
In most cases though, you do not know the propertyname and bind to an element in the collection.
Then it would like more:
myDoubleCollection.Add(someDoubleValue); //do this for each item in the itemssource of the grid
int index=myDoubleCollection.Count-1;
newColumn.Binding = new Binding(string.Format("myDoubleCollection[{0}]",index));
So this works also.
Another thing to keep in mind is the deletion of columns. This requires some extra work.
That's a lot of questions rolled into one! I suggest you do a bit more background research before asking questions. I would recommend that your read this codeproject article I wrote about the WPF DataGrid a while back:
http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx
It will answer most of your questions for you!
Take a look at the MVVM pattern, it'll be a huge help as you create this application.
What you want is an ObservableCollection in the ViewModel. You'll bind the ItemsSource property of the datagrid to this collection. Then have your columns bind to various properties on to display them. Whenever this ObservableCollection has an item appended, your front end should update automatically.
To have a column autosize, set the Width="*".
Here's a sample of a datagrid with MVVM
<DataGrid ItemsSource="{Binding FireAlarmCollection}" SelectedItem="{Binding SelectedFireAlarm, Mode=TwoWay}" AutoGenerateColumns="True" CanUserSortColumns="True" HorizontalScrollBarVisibility="Visible" CanUserResizeColumns="True">
</DataGrid>
As you continue your effort, post separate questions for each issue.
I have a UserControl I've written to display a few properties from a custom object. There are multiple instances of these objects so I have an ObservableCollection of them so I can set them as an ItemsSource binding to a ListView. Now I can get an instance of this UserControl show up for each instance of my class in my ListView.
The problem is I don't really want the behavior of a ListView. I don't want the user to be able to select the entire UserControl. In fact, the user should be able to select individual elements in the UserControl.
I thought about just using a StackPanel to put these UserControls in, but it doesn't have an ItemesSource property. Is there an easy way to make this happen?
Replace your ListView with an ItemsControl and set the ItemTemplate to a suitable DataTemplate for your objects. You can set the ItemsPanel if you want to change how the panel lays out the items.
<ItemsControl ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource ItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
See this example