ListBox with hyperlink -> selection changed - silverlight

I want to do with xaml bindings such feature:
Listbox contains hyperlinks.
When hyperlink clicked - we go to another frame
But also SelectedItem must changed, and on another frame we show info about selected item.
I want it without subscribing click/selected events. Only declarative
Example of my listbox
<ListBox Grid.Row="1"
x:Name="OrderTypesListBox"
ItemsSource="{Binding OrderTypes, Mode=OneWay}"
SelectedItem="{Binding SelectedCall.OrderType, Mode=TwoWay}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" />
<HyperlinkButton Style="{StaticResource LinkStyle}" NavigateUri="/WindowPage" TargetName="ContentFrame" Content="WindowPage"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now solve like that
<ListBox Grid.Row="1"
x:Name="OrderTypesListBox"
ItemsSource="{Binding OrderTypes, Mode=OneWay}"
SelectedItem="{Binding SelectedCall.OrderType, Mode=TwoWay}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<HyperlinkButton
TargetName="ContentFrame"
NavigateUri="{Binding OrderTypeNextPage}"
Content="{Binding Name}"
Click="HyperlinkButton_Click"
Tag="{Binding}"
/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
OrderTypesListBox.SelectedItem = (sender as HyperlinkButton).Tag;
}

Don't use a HyperlinkButton. Perform the needed actions when the SelectedItem changes in your ViewModel.
Edit: If you need to respond to all click events even if the item is already selected then you can use a Behavior to do this. Just create a behavior for the TextBlock that navigates on the TextBlock click event.
Edit2: Behaviors are pretty simple to code up and easy to use (and don't break the MVVM paradigm).
public class NavigatingTextBlockBehavior : Behavior<TextBlock>
{
protected override void OnAttached()
{
AssociatedObject.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseDown);
}
private void OnMouseDown(object sender, MouseButtonEventArgs e)
{
NavigationService.Navigate(new Uri("/WindowPage"));
}
}

Related

How to get the checkbox column sender's datagrid parent

Hi I have a datagrid (xaml code below):
<DataGrid.Columns>
<DataGridTextColumn Header="FLEET" IsReadOnly="True" Width="1*" Binding="{Binding FLEET, UpdateSourceTrigger=PropertyChanged}" />
<DataGridTemplateColumn Header="SELECTED?" Width="1*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Viewbox Margin="-0.2" Height="18.5">
<CheckBox IsThreeState="True" IsChecked="{Binding Path=isSelected, UpdateSourceTrigger=PropertyChanged}" Click="FSC_CheckBox_Click"/>
</Viewbox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
The click events:
private void FSC_CheckBox_Click(object sender, RoutedEventArgs e)
{
......
}
Is there a way I can get the the parent datagrid object from the click sender? I've tried this link
Get containing row from a CheckBox inside of a DataGrid, but it didn't work because of the viewbox and datatemplate(I guess).
Any suggestions is appreciated. Thank you.
The click event handler will get the sender, which you can cast to checkbox.
I reckon the simplest approach is to abuse the Tag property on your checkbox.
That can be any old object you fancy.
You can use a relativesource binding for that.
Something like:
<CheckBox Tag="{Binding RelativeSource={Relativesource AncestorType=DataGrid}}"
Grab it off there, roughly:
private void FSC_CheckBox_Click(object sender, RoutedEventArgs e)
{
var cb=(CheckBox)sender;
var parentDataGrid = (DataGrid)cb.Tag;
}
This is air code, I don't have a datagrid with a checkbox and a click handler to try it out with easily so there may be some typo lurking.

How to disable deselection of items in ListView?

I've got
<ListView SelectionMode="Single" SelectedIndex="0" ItemsSource="{Binding AccountViewModels}" SelectedItem="{Binding SelectedItem}" Style="{StaticResource AccountsList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<LocalViews:AccountView Margin="{StaticResource ControlMargin}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
Is there a way to disable deselection of an item from the ListView (i.e. ctrl+click)? In other words, I don't want the user to be able to de-select an item, but of course it's OK to select another item.
Since this functionality is purely view/control related it should not be implemented in the view model but you could handle the PreviewMouseLeftButtonDown event of the ListBoxItem container like this:
<ListView SelectionMode="Single" SelectedIndex="0" ItemsSource="{Binding AccountViewModels}" SelectedItem="{Binding SelectedItem}" Style="{StaticResource AccountsList}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ItemPreviewMouseLeftButtonDown" />
</Style>
</ListBox.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<LocalViews:AccountView Margin="{StaticResource ControlMargin}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
private void ItemPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
ListBoxItem lbi = sender as ListBoxItem;
e.Handled = lbi.IsSelected;
}
One way to handle this would be to use binding and add logic to disallow de-selection in the view model.
From this answer, change the IsSelected as follows:
private bool isSelected;
public bool IsSelected
{
get { return isSelected; }
set
{
if (value && !isSelected)
{
isSelected = value;
RaisePropertyChanged("IsSelected");
}
}
}

How to subscribe event in datatemplate of listview

In WPF I have a listview that is bound to an ObservableCollection.
XAML:
<ListView Name="listView" DockPanel.Dock="Top" ItemsSource="{Binding Path=ListOfOldData}" SelectedItem="{Binding Path=SelectedOldData, Mode=TwoWay}" SelectionMode="Single">
<ListView.ContextMenu>
<ContextMenu>
<Button Content="Load" Command="{Binding Path=LoadCommand}" Name="loadButton" Height="23" Width="75" DockPanel.Dock="Left"/>
<!-- Is working just fine -->
</ContextMenu>
</ListView.ContextMenu>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock MouseLeftButtonDown="TextBlock_MouseLeftButtonDown"
Text="{Binding Path=Name}" FontWeight="Bold"><TextBlock Text=" - " FontWeight="Normal"/><TextBlock Text="{Binding Path=UpdateDatum}" FontWeight="Normal"/></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
What I actually wanted to receive is a double-click on the selected-item. As I can't bind a command to a textblock in xaml (can I?) I tried doing this via the MouseLeftButtonDown-Event. But the event is never received!
C# (in code behind):
private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("MouseLeftButtonDown received!");
}
What am I doing wrong? How can I receive the event? Btw.: The command of the contextmenu is working just fine :)
UPDATE I found my error --> I added the event in the wrong usercontrol. Damn my missing concentration. Sorry for bugging you all.
you can simply use InvokeCommandAction from blend sdk (System.Windows.Interactivity.dll)
<ListView x:Name="lvw" ItemsSource="{Binding ListOfOldData}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding Path=OpenCommand}"
CommandParameter="{Binding ElementName=lvw, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
EDIT:
viewmodel should look something like this:
public List<object> ListOfOldData{ get; set; }
private DelegateCommand<object> _openCommand;//or RelayCommand
public DelegateCommand<object> OpenCommand
{
get { return _openCommand?? (this._openCommand= new DelegateCommand<object>(this.Execute)); }
}
private void Execute(object obj)
{
//obj is your selectedItem
}
ps: dunno your type thats why object
The ListView has a DoubleClick MouseEvent.
This should do it :
<ListView MouseDoubleClick="DoubleClickOnIt">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold">
<TextBlock Text=" - " FontWeight="Normal"/>
<TextBlock Text="{Binding Path=UpdateDatum}" FontWeight="Normal"/>
</TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
<ListViewItem>
dddd
</ListViewItem>
<ListViewItem>
eeeee
</ListViewItem>
</ListView>
And the code behind :
private void DoubleClickOnIt(object sender, MouseButtonEventArgs e)
{
var listView = sender as ListView;
var selectedItem = listView.SelectedItem;
Console.WriteLine("received!");
}

Print all content in ScrollViewer - Silverlight

I am showing some 100s of records in ScrollViewer Control. When I print the ScrollViewer Control it prints only the current view (10 records). How can I print all the 100s of data at once?
You might want to use PrintDocument class in Silverlight.
The usage is like..
in XAML file create List as
<ScrollViewer Height="300" VerticalScrollBarVisibility="Auto">
<ItemsControl x:Name="printSurface">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
Height="25">
<TextBlock Width="100"
Text="{Binding Name}" />
<TextBlock Width="75"
Text="{Binding Genre.Name}" />
<TextBlock Width="50"
Text="{Binding Price, StringFormat=c}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
And Code behind looks like.
void printButton_Click(object sender, RoutedEventArgs e)
{
PrintDocument doc = new PrintDocument();
doc.PrintPage += new EventHandler<PrintPageEventArgs>(doc_PrintPage);
doc.Print("Page title");
}
void doc_PrintPage(object sender, PrintPageEventArgs e)
{
// Stretch to the size of the printed page
printSurface.Width = e.PrintableArea.Width;
printSurface.Height = e.PrintableArea.Height;
// Assign the XAML element to be printed
e.PageVisual = printSurface;
// Specify whether to call again for another page
e.HasMorePages = false;
}

How to find sibling of a control that raised an event in DataGrid WPF

I have a DataGrid whole columns are given below.
<my:DataGrid.Columns>
<my:DataGridTemplateColumn Header="Last Name" MinWidth="160" SortMemberPath="[LAST_NAME]">
<my:DataGridTemplateColumn.CellTemplate >
<DataTemplate>
<TextBlock Name="lblLastName" Padding="5"
Text="{Binding [LAST_NAME]}" />
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
<my:DataGridTemplateColumn Header="New Age Group" IsReadOnly="True"
MinWidth="130">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding AgeGroupId}"
DisplayMemberPath="AgeGroupName" ItemsSource="{Binding}"
Name="ddlNewAgeGroup" Loaded="ddlNewAgeGroup_Loaded"/>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
<my:DataGridTemplateColumn Header="Update" MinWidth="75" Width="100">
<my:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Update" Name="btnUpdate" Click="btnUpdate_Click"/>
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
</my:DataGrid.Columns>
On btnUpdate_Click event I want to get the value that has been set on ddlNewAgeGroup
But I dont know how to find this Combobox on Button Click Event in WPF. I am using DataTables to Bind grids.
(e.OriginalSource as Button).DataContext should be the object binded to your row, so it should have AgeGroupId property (as seen from ComboBox.SelectedValue), and it's a collection (as seen from ComboBox.ItemsSource). So you may find use AgeGroupName this way:
private void Grid_Click(object sender, RoutedEventArgs e) {
var row = (e.OriginalSource as Button).DataContext as %YourDataType%;
var agegroupname = row.First(item => item.AgeGroupId == row.AgeGroupId).AgeGroupName;
// TODO: do what you need with "agegroupname".
}
PS. Please set ComboBox.SelectedValuePath to something like AgeGroupId: without it, ComboBox.SelectedValue is equal to a whole record, not just Id

Resources