How to update binding source for checkbox from template? - c#

I have a template (TextBlock + CheckBox) for items in LonglistSelector but I wasn't able to figure out how to refresh binding. The CheckBox is bound to a boolean property. Only way that worked so far was to navigate to same XAML page with different parameter however this "solution" is unusable.
I've found some examples how to use UpdateSource() with TextBox but none with CheckBox from template.
Here is my CheckBox from teplate. Many things are probably useless, I tried everything I found. Binding is working but it does not refresh so I have to navigate to another page for example and then it is refreshed.
<CheckBox BorderThickness="2"
VerticalAlignment="Center"
x:Name="TemplateCheckBox"
IsChecked="{Binding IsDone, UpdateSourceTrigger=Explicit, Mode=TwoWay}"
Checked="TemplateCheckBox_Checked"
Unchecked="TemplateCheckBox_Checked"
/>
EDIT: I found easy way how to update items in LonglistSelector. Just create another empty List set it as a ItemsSource and just afterwards set original list as ItemsSource.

<CheckBox BorderThickness="2" **Loaded="OnLoaded"**
VerticalAlignment="Center"
x:Name="TemplateCheckBox"
IsChecked="{Binding IsDone, UpdateSourceTrigger=Explicit, Mode=TwoWay}"
Checked="TemplateCheckBox_Checked"
Unchecked="TemplateCheckBox_Checked"
/>
private List<CheckBox> chkList=new List<CheckBox>();
private void OnLoaded(object sender,EventArgs e)
{
if(!chkList.Contians(sender as CheckBox))
{
chkList.Add(sender as CheckBox);
}
}
private void UpdateSource()
{
foreach(CheckBox chk in chkList)
{
chk.GetBindingExpression(CheckBox.IsChekcedProperty).UpdateSource();
}
}

Related

CheckBox not Updating when Source Changed

I'm still very new to WPF/XAML so bear with me here...
I have a DataGrid that contains three columns: 2 DataGridTextColumns and a DataGridTemplateColumn, which contains a CheckBox. The DataGrid is bound to a collection that displays objects of type Field. The IsChecked property of the CheckBox is also bound to a property in a ViewModel.
What I'd like to be able to achieve is that when a Field i.e. a row in the DataGrid is clicked, the Field's corresponding CheckBox becomes checked or unchecked.
I have bound to the SelectedItem of the DataGrid and can retrieve the Field that's clicked. I then set the "IsChecked" property of the Field accordingly.
However, the check in the CheckBox does not appear (or disappear) seemingly until the row in the DataGrid is repainted. That is, if I scroll down so that the row disappears out of view and then scroll back up to it, the check is displayed in the CheckBox. I am raising an INotifyPropertyChanged event when the IsChecked property value is set.
Would anyone be able to suggest what might be going wrong here?
The code for the column containing the CheckBox is shown below.
Any ideas/suggestions/help would be greatly appreciated.
Many thanks.
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5" />
</DataTemplate>
</DataGridTemplateColumn>
</DataGridTemplateColumn>
Try this:
First define new DataGridRow style to subscribe PreviewMouseButtonDownEvent:
<Style TargetType="{x:Type DataGridRow}">
<EventSetter Event="PreviewMouseLeftButtonDown"
HandledEventsToo="True"
Handler="PreviewDataGridRowClick"
></EventSetter>
</Style>
And eventhandler:
private void PreviewDataGridRowClick(object sender, MouseButtonEventArgs e)
{
var datagridRow = (DataGridRow) sender;
var underlyingVm = datagridRow.Item as YourVM;
underlyingVm.IsChecked = !underlyingVm.IsChecked;
e.Handled = true;
}

Disable the drop down menu of a WPF ComboBox

I have a ComboBox as specified below:
<ComboBox Height="31" Margin="7,7,0,0" Name="callerID" IsEditable="True" Background="LightBlue" KeyDown="callerIDbar_KeyDown" Foreground="White" FontSize="17" FontWeight="Bold" HorizontalContentAlignment="Center" VerticalAlignment="Top" Grid.Row="0" Grid.Column="0" />
storedCalls is a collection of phone numbers that will be populated to the ComboBox.Items:
foreach (string call in storedCalls)
{
if (call != "Enter a number to dial")
callerID.Items.Add(call);
}
All this works fine. I populate the Items primary because I like the autocomplete that is driven by the values in the ComboBox's Items collections. Is there a way the XAML to disable the drop down error, and disable the drop down menu? I.e. make a simple auto complete textbox like control?
I have seen full on TextBox controls that include a bunch of code-behind and complicated markup, and this is not what I am looking to do. I just need to disable the ability of the drop down menu from showing.
You can handle the DropDownOpened event and then close it.
So in n the XAML you get:
<ComboBox x:Name="cb" DropDownOpened="cb_DropDownOpened"/>
And in Code Behind:
private void cbCategoria_DropDownOpened(object sender, EventArgs e)
{
ComboBox cb = sender as ComboBox;
cb.IsDropDownOpen = false;
}
I prefear this solution reather than set MaxDropDownHeight to 0.
Your choice.

GridView Row Does not get select or Affected When Checkbox checked on Grid

I am using WPF Application Form with Telerik Gridview using C#.
In that Gridview i inserted checkboxes using Data template.
Its created but when i click or check the checkbox the current row is not getting selected.
How can i solve this problem?
Please anyone tell me the solution of this problem.
My xaml code for creating checkbox in grid is:
<telerik:GridViewDataColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<CheckBox Name="CheckBox" IsChecked="{Binding IsSelected,UpdateSourceTrigger=PropertyChanged}" Click="CheckBox_Click" />
</StackPanel>
</DataTemplate>
</telerik:GridViewDataColumn.CellTemplate>
In that checkbox i have created click event.
And also i want to know the current row number of the CheckBox Placed row in the gridview in checkbox click event. Give me some suggestion for this.
Here My CheckBox Click event Code:
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
CheckBox selectedCheckbox = (CheckBox)sender;
//this.selectedCasePackRadGrid -- This is my gridview
// Here I want to get the selected row number
}
Thanks in Advance.
First of all, I don't see you actually setting the row as Selected anywhere.
Your binding currently is setting a property in your DataContext called IsSelected. If this property actually exists, you can bind it to GridViewRow.IsSelected in a style
<Style TargetType="{x:Type telerik:GridViewRow}">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
If it doesn't exist in your data object, you need to use a RelativeSource binding to find the GridViewRow and bind to it's IsSelected property
Checked="{Binding RelativeSource={RelativeSource AncestorType={x:Type telerik:GridViewRow}}, Path=IsSelected}"
As for finding the row number, there is no RowIndex property I know of that you can use to find the row number. One alternative is to get the GridView's ItemsSource and call IndexOf(dataobject), however that does break the separation of MVVM layers
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
CheckBox checkBox = (CheckBox)sender;
var dataItem = checkBox.DataContext as MyDataItem;
var parentDataObject = myGridView.ItemsSource as SomeDataObject;
if (dataItem == null || parentDataObject == null)
return;
var index = parentDataObject.SomeCollection.IndexOf(dataItem);
// Do something with index
}
There are also other alternatives such as setting AlternationCount to something higher than the the number of rows, and accessing GridViewRow.AlternationIndex, although I don't know if that will work with Telerik's GridView
But perhaps the best thing you could do is evaluate what you actually need the index for, and see if you can use some other alternative to accomplish what you want. For example, if you want to pass the index of the selected row to a button command, it would be better to just pass the SelectedItem as the CommandParameter.

Populate ListBox after clicking Submit button

I want to populate a listbox after inputting text into a text box and clicking Submit. Seems simple I know, but I'm new to Data Binding and WPF...
Here's my code so far... I don't know if the XAML is correct, and of course I have nothing in the event code behind... any help would be appreciated.
XAML:
<ListBox ItemsSource="{Binding ElementName=accountaddTextBox, Path=SelectedItem.Content, Mode=OneWay, UpdateSourceTrigger=Explicit}" Height="164" HorizontalAlignment="Left" Margin="12" Name="accountListBox" VerticalAlignment="Top" Width="161" />
Code behind:
private void okBtn_Click(object sender, RoutedEventArgs e)
{
}
Your current binding is telling the ListBox to find an object named accountaddTextBox, and bind to its SelectedItem.Content. I am assuming that accountaddTextBox is a TextBox, and SelectedItem is not a valid property on TextBox, so your binding is invalid.
It would be far better to bind your ListBox to an ObservableCollection<string> that is located in your code-behind or ViewModel, and have your button add a new object to that collection. Since it is an ObservableCollection, the UI will automatically update
For example,
<ListBox ItemsSource="{Binding SomeObservableCollection}" />
private void okBtn_Click(object sender, RoutedEventArgs e)
{
SomeObservableCollection.Add(accountaddTextBox.Text);
}

Getting value back from ListBox to EventHandler in WP7

In my WP7 application I have ListBox control that binds with List<ItemTemplate> collection. On each ListBoxItem I have Click event which navigates to DisplayItem.xaml. Each ItemTemplate object has Id property which has to be passed to DispalyItem.xaml. I know that I can pass this value from Click EventHandler to DisplayItem.xaml using QueryString but how do I pass it from ListBox item to EventHandler ?
<ListBox x:Name="listBoxItems">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse Fill="red" Width="30" Height="30"></Ellipse>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Status}" FontSize="35" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<HyperlinkButton Content="{Binding ItemContent}" Name="itemButton" Click="itemButton_Click"/>
</StackPanel>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu>
<toolkit:MenuItem Header="edit"/>
<toolkit:MenuItem Header="delete"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Id property is not mentioned in the above code because I just simply didnt know where to place it. Generally I want to know how can I get Id property back to the click EventHandler ? I'm sorry if this question is basic for you but I'm new to that and i wasn't sure how to google that.
If you're really new to Windows Phone 7, you may want to stop using the "Click" event and instead use the ListBox.SelectionChanged event. If you are bound to List<MyObject>, you could do the following:
In your XAML:
<ListBox SelectionChanged="NavigateToMyDetail" ... >
Then in the code behind, you would have something like this:
private void NavigateToMyDetail(object sender, SelectionChangedEventArgs e)
{
// Make sure that the ListBox change wasn't due to a deselection
if(e.AddedItems != null && e.AddedItems.Count == 1)
{
MyObject selectedItem = (MyObject)e.AddedItems[0];
// Now you have access to all your MyObject properties
// and you can pass that to your new page as a parameter
NavigationService.Navigate(new Uri("DisplayItem.xaml?ItemID=" + selectedItem.id.ToString(), UriKind.Relative));
}
}
And you can get that ID with the following code (probably in your "OnNavigatedTo" method).
string myItemID = null;
if(this.NavigationContext.QueryString.ContainsKey("ItemID"))
myItemID = NavigationContext.QueryString["ItemID"];
Hope that helps. The other way to try to get it is to give your ListBox a x:Name and then references it in your Click handler like:
private void MyClickHandler(object sender, System.Windows.RoutedEventArgs e)
{
MyObject selectedObject = (MyObject)MyListBoxName.SelectedItem;
}
There is a much simpler solution if you use data binding with an MVVM viewmodel behind it.
Simply bind you view to a property in the view model for the listbox "Source" and then also do the same for the ListBox "SelectedItem" or "SelectedIndex" properties, then you will have all you need accessible where ever you needed.
Only think to be aware of (as I'm uncertain if it ever got fixed) is to fixed the selected index property when an item has been selected, if you do not reset it to -1 then if the user returns to the list they cannot select the same item. (do this in the codebehind for the click event)
Also if you use MVVM and databinding you can enact an action from the change of the Selected item rather than using Code behind to drive the direction, always an option to keep things simple (but not mandatory)
I have also came to my own solution. I'm not sure If its correct bit its certainly solving my problem for now.
I found this CommandParameter property of object HyperlinkButton. I bound my MyObject.Id property value to it.
<HyperlinkButton Content="{Binding ItemContent}" Click="itemButton_Click" CommandParameter="{Binding Id}" />
Then in my EventHandler i said:
private void itemButton_Click(object sender, RoutedEventArgs e)
{
HyperlinkButton butt = sender as HyperlinkButton;
NavigationService.Navigate(new Uri("/ViewItem.xaml?itemId=" + butt.CommandParameter.ToString(), UriKind.Relative));
}
It works as I need it to work but I'm not sure If i should use it in my applications in the future.

Categories