How to focus into AutoCompleteBox - c#

How to focus into AutoCompleteBox? I've tried many of code by searching on stackover but not getting focus. here is some code which i wrote.
<controls:AutoCompleteBox Name="SearchTextBox" IsTextCompletionEnabled="True" SelectedItem="{Binding Code, Mode=TwoWay}" Grid.Column="1" PreviewKeyDown="SearchTextBox_PreviewKeyDown" >
<controls:AutoCompleteBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Code}"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</controls:AutoCompleteBox.ItemTemplate>
</controls:AutoCompleteBox>
and for focus i've creating a class named FocusableAutoCompleteBox
public class FocusableAutoCompleteBox : AutoCompleteBox
{
public new void Focus()
{
var textbox = Template.FindName("SearchTextBox", this) as AutoCompleteBox;
if (textbox != null) textbox.Focus();
}
}
and focus by
new FocusableAutoCompleteBox().Focus();
but errors appears
Object Reference not set to an instance of object
I also tried SearchTextBox.Focus(); but not getting result.

this works for me.
Keyboard.Focus(SearchTextBox);
SearchTextBox.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));

Related

Access unnamed control in xaml from code behind

I've got about 20 of the following underneath a ComboBox (which means that I can't use any x:Name parameter due to duplicate naming):
<ComboBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="folder/someimage.png" Height="20" Width="20"/>
<TextBlock Text="SampleText" Margin="5,0,0,0"/>
</StackPanel>
</ComboBoxItem>
How can I access the string from the TextBlock inside the SelcetionChanged event?
Currently when I choose the item normally, the selected text (of my ComboBox) is set to
System.Windows.Controls.ComboBoxItem
This is the return value from the ComboBoxItem.ToString() method!
How can I change the return type of my xaml based ComboBoxItem?
After long research I've found a solution. I've created a new UserControl and then added it as item of my ComboBox.
MyComboBoxItem.xaml:
<StackPanel Orientation="Horizontal">
<Image x:Name="img" Source="{Binding Image, ElementName=myComboBoxItem}" Height="18" Width="18"/>
<TextBlock x:Name="txt" Text="{Binding Text, ElementName=myComboBoxItem}" Margin="5,0,0,0"/>
</StackPanel>
MyComboBoxItem.xaml.cs:
public string Text
{
get { return txt.Text; }
set { txt.Text = value; }
}
public override string ToString()
{
return Text;
}
MainWindow.xaml:
<ComboBox>
<local:MyComboBoxItem Image="image1.png" Text="Item1"/>
<local:MyComboBoxItem Image="image2.png" Text="Item2"/>
<local:MyComboBoxItem Image="image3.png" Text="Item3"/>
</ComboBox>
Now it works like a charm and does exactly what I've wanted.

ListBox.ItemContainerGenerator.ContainerFromIndex Returns null

For my Windows Phone 8 App I have a Listbox element like below;
when I press multiselect icon on AppBar, I want to show checkboxes inside DataTemplate.
So users can make multiselect on items.
I have 50 elements bound on this Listbox and always at the index 11 ItemContainerGenerator.ContainerFromIndex returns null, plus some other items at rest of the list. So around 10 items out of 50 as returning as null.
There are some answers for WPF like applying Dispatcher.BeginInvoke or UpdateLayout, ScrollIntoView but none of them is working.
On the other hand if I scroll through list and then press AppBar icon it just works fine. But users can directly press on icon right after data bound and they will not see some of the checkboxes.
Is there any workaround for this issue for Windows Phone 8?
<ListBox Name="ResultListBox" ItemsSource="{Binding}"
SelectionChanged="ResultListBox_OnSelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,10" Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<CheckBox Name="CheckBox" Visibility="Collapsed">
</CheckBox>
<Image Source="{Binding url}"
Width="125"
Height="125"
VerticalAlignment="Top"
Margin="0,0,5,0"></Image>
</StackPanel>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding title}"
VerticalAlignment="Top"
FontFamily="Portable User Interface"></TextBlock>
</StackPanel>
<StackPanel>
<TextBlock Text="{Binding description}"
FontFamily="Portable User Interface"></TextBlock>
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
void appBarButtonSelect_Click(object sender, EventArgs e)
{
//Dispatcher.BeginInvoke(delegate
//{
//});
for (int i = 0; i < ResultListBox.Items.Count; i++)
{
//ResultListBox.UpdateLayout();
//ResultListBox.ScrollIntoView(i);
DependencyObject item = ResultListBox.ItemContainerGenerator.ContainerFromIndex(i);
if (item != null)
{
CheckBox checkBox = FindFirstElementInVisualTree<CheckBox>(item);
if (checkBox != null)
{
checkBox.Visibility = Visibility.Visible;
}
}
else
{
Debugger.Break();
}
}
}
I think you're using ScrollIntoView + UpdateLayout incorrectly,
You're passing it an index, when it needs an object that is directly related to the ItemsSource
So if your ItemsSource is an ObservableCollection do this:
object o = ((ObservableCollection<sample_model>)this.myListBox.ItemsSource)[INDEX];
this.myListBox.ScrollIntoView(o); // call this first
this.myListBox.UpdateLayout(); // call this second
Then your ItemContainerGenerator.ContainerFromIndex(INDEX) will not be NULL.

binding data - inotifypropertychanged does not work

I have a listBox1 in which data are binding from the list. Then I want to when I select any item from listBox1 in listBox2 will binding data from another list.
private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
Teams teams = (Teams)listBox1.SelectedItems[0];
getH2hResults("//td[#class='hell']", teams.Team1, teams.Team2); // add elements to list
getH2hResults("//td[#class='dunkel']", teams.Team1, teams.Team2); // and here also
listBox2.ItemsSource = lists.h2hList;
}
On the first time this work, but for the twice time listBox2 doesn't displays new data.
public class Lists : BindableBase
{
public Lists()
{
_teamsList = new List<Teams>();
_h2hList = new List<H2H>();
}
private List<Teams> _teamsList;
public List<Teams> teamsList
{
get
{
return _teamsList;
}
set
{
if (value != _teamsList)
{
_teamsList = value;
RaisePropertyChanged("teamsList");
}
}
}
private List<H2H> _h2hList;
public List<H2H> h2hList
{
get
{
return _h2hList;
}
set
{
if (value != _h2hList)
{
_h2hList = value;
RaisePropertyChanged("h2hList");
}
}
}
}
And XAML
<ListBox Name="listBox1" Width="300" Height="300"
VerticalAlignment="Top"
HorizontalAlignment="Left"
ItemsSource="{Binding teamsList}" SelectionChanged="listBox1_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Foreground="#FF4273CD" Text="{Binding Team1, Mode=TwoWay}"></TextBlock>
<TextBlock Text=" vs " FontWeight="Bold"></TextBlock>
<TextBlock Foreground="#FF4273CD" Text="{Binding Team2, Mode=TwoWay}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox Name="listBox2" Grid.Column="1" Width="300" Height="300"
VerticalAlignment="Top"
HorizontalAlignment="Left"
ItemsSource="{Binding h2hList}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding date, Mode=TwoWay}"></TextBlock>
<TextBlock Text="{Binding result, Mode=TwoWay}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
RaisePropertyChanged("teamList");
is Wrong your propery is named 'teamsList' with an S,
change to:
RaisePropertyChanged("teamsList");
It is the public property you bind to and notify changes of,
edit:
also change your binding:
ItemsSource="{Binding teamList}"
to
ItemsSource="{Binding teamsList}"
Edit 2:
listBox2.DataContext = xxx
Not itemsource = xxx
With the line (in listBox1_SelectionChanged)
listBox2.ItemsSource = lists.h2hList;
you are effectively removing the binding from the ItemsSource property of listBox2.
Instead, you should only update the h2hList property in your Lists class (which presumably happens in getH2hResults) and remove the above line from your code.
Note however that it is not sufficient to clear and re-fill that list. You need to set the h2hList property in order to get a property change notification raised:
var newList = new List<H2H>();
// fill newList before assigning to h2hList property
lists.h2hList = newList;
If you want to keep the list and just change its elements, you would need to use ObservableCollection<H2H> instead of List<H2H> as collection type. This would be the better approach anyway, as you would not have to care for when exactly you add elements to a newly created collection.

How to bind multiple eventhandlers on WindowsPhone 8 using XAML?

I'm about to make a control page that has several textblock.
each textblock will be "linked" to another page,
here's my xaml part
.........<phone:LongListSelector x:Name="settingSelector" ItemsSource="{Binding}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel toolkit:TiltEffect.IsTiltEnabled="True" Tap="{Binding TapMethod, Mode=TwoWay}" >
<TextBlock Text="{Binding SetTitle}" FontSize="43" />
<TextBlock Text="{Binding SetDescription}" FontSize="19" Margin="0 0 0 10" />
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>..........
when I try this code behind :
.........public class SettingProperty
{
public string SetTitle{get; set;}
public string SetDescription{get; set;}
public string TapMethod{get; set;}
public SettingProperty(string setTitle, string setDescription, string tapMethod)
{
SetTitle = setTitle;
SetDescription = setDescription;
TapMethod = tapMethod;
}
}
List<SettingProperty> DataSetting()
{
List<SettingProperty> settingCollection = new List<SettingProperty>();
settingCollection.Add(new SettingProperty("Saldo", "cek saldo", "saldo_Tap"));
return settingCollection;
}
private void saldo_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
NavigationService.Navigate(new Uri("/saldo.xaml", UriKind.Relative));
}..........
I directly deployed them to my L520, I'm prety sure the culprit is the "Tap" binding on my stackpanel, when I omit it, the code works.
Did I miss something, or my whole method is just wrong?
our understanding of the "Tap" event is wrong.
You have two options here:
Either you clearly specify a METHOD NAME (not a string) as a event handler for the Tap event. For example:
Tap="MyControl_Tap"
In this case you must have a MyControl_Tap method in your control's code behind
OR, since you seem to be using the MVVM pattern, you have to create a ICommand, and then include your whole StackPanel in a Button, like this:
...<DataTemplate>
<Button Command="{Binding MyCommandProperty}">
<StackPanel toolkit:TiltEffect.IsTiltEnabled="True" >
<TextBlock Text="{Binding SetTitle}" FontSize="43" />
<TextBlock Text="{Binding SetDescription}" FontSize="19" Margin="0 0 0 10" />
</StackPanel>
</Button>
...

How can I raise a custom Routed Event from a DataTemplate?

I have a User Control,called dCB_Props that contains several objects, most importantly a ComboBox that's bound to an Observable Collection. Though the collection can take any object, it will normally take a UserControl called EditDeleteItem. I've set dCB_Props to use EditDeleteItem as an ItemsTemplate but the events aren't fired. If, on the other hand, I add an instance of EditDeleteItem then the events will get fired. I can't add items this way because the EditDeleteItem will host other controls and I'd need to use different DataTemplates.
EditDeleteItem has two Routed Events called EditClick and DeleteClick.
When the collection changes it fires an event that checks if the item added is of type EditDeleteItem. If so, then it adds handlers to the two aforementioned events.
Part of the xaml for EditDeleteClick:
<WrapPanel x:Name="wp" HorizontalAlignment="Right" Visibility="Hidden" VerticalAlignment="Center" Margin="0,0,5,0">
<Button x:Name="PART_Edit" Width="20" Height="20" Content="{DynamicResource dPen}" Style="{DynamicResource dTranspButton}" Click="btnEdit_Click"/>
<Button x:Name="PART_Delete" Width="20" Height="20" Content="{DynamicResource dCross}" Style="{DynamicResource dTranspButton}" Click="btnDelete_Click"/>
</WrapPanel>
<Label Content="{TemplateBinding Content}" Margin="2,0,45,0" Padding="0,0,0,0" HorizontalAlignment="Left" VerticalContentAlignment="Center"/>
Part of the xaml for dCB_Props:
<ComboBox HorizontalContentAlignment="Stretch" x:Name="PART_cb" Background="Transparent" Margin="0,0,0.367,0" d:LayoutOverrides="HorizontalAlignment" ItemsSource="{Binding Items, ElementName=dcb}" IsDropDownOpen="{Binding IsDropDownOpen,ElementName=dcb, Mode=TwoWay}" Grid.ColumnSpan="3" Style="{DynamicResource DaisyComboBox}" />
<Button x:Name="PART_Edit" Width="20" Height="20" Content="{DynamicResource dPen}" Visibility="Hidden" Style="{DynamicResource dTranspButton}" Margin="2.581,1.48,17.778,-1.48" Grid.Column="1" Click="btnEdit_Click"/>
<Button x:Name="PART_Delete" Width="20" Height="20" Content="{DynamicResource dCross}" Visibility="Hidden" Margin="22.602,1.48,-2.243,-1.48" Style="{DynamicResource dTranspButton}" Grid.Column="1" Click="btnDelete_Click"/>
<Button x:Name="PART_Add" Content="+" Grid.Column="3" Margin="0,0,0,0" Style="{DynamicResource dTranspButton}" Click="btnAdd_Click"/>
Note the above two are codes just for objects, I've left out Column Definitions, Event Triggers, etc.
Part of dCB_Props.xaml.cs code is:
public partial class dCB_Props : UserControl
{
public dCB_Props()
{
this.InitializeComponent();
Items= new ObservableCollection<object>();
Items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Items_CollectionChanged);
}
void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
foreach (var o in e.NewItems)
{
if (o.GetType() == typeof(EditDeleteItem))
{
EditDeleteItem itm = (EditDeleteItem)o;
itm.EditClick += new RoutedEventHandler(ItemEdit_Click);
itm.DeleteClick += new RoutedEventHandler(ItemDelete_Click);
}
}
}
}
...//I've left some code here since I don't deem it's that important for the situation
private void ItemEdit_Click(object sender, RoutedEventArgs e)
{
DependencyObject d = GetTemplateChild("PART_cb");
if (d == null) return;
ComboBox cb = (ComboBox)d;
if (cb.SelectedItem != null) RaiseEvent(new RoutedEventArgs(EditClickEvent, e.OriginalSource));
}
}
The above works if I add an item of type EditDeleteItem and remove the ItemTemplate property for the Label that resides inside dCB_Props. It also works if I set the ItemTemplate, shown below, in EditDeleteItem's ContentTemplate. But, as mentioned, I need to use different Data Templates so I assume all Data Templates will have to reside in a Resource Dictionary and then I'd have to use a Template Selector.
Data Template:
<DataTemplate x:Shared="false" x:Key="TagTemplate">
<local:EditDeleteItem x:Name="edItem">
<local:EditDeleteItem.Content>
<StackPanel>
<TextBlock Text="{Binding Path=Content.Label}"/>
<CheckBox Content="Isolated" IsChecked="{Binding Content.IsIsolated}"/>
<CheckBox Content="Match Case" IsChecked="{Binding Content.MatchCase}"/>
<CheckBox Content="Include" IsChecked="{Binding Content.Include}"/>
</StackPanel>
</local:EditDeleteItem.Content>
</local:EditDeleteItem>
</DataTemplate>
I believe I need to use command bindings. But not really sure where to put the CommandBindings, and not so sure how to use them, though I've read a page or two.
Thanks,
Hassan
The events are fired, but you don't catch them, because subscription in Items_CollectionChanged never occurs if ItemTemplate is used.
You should understand how ItemsControl (and ComboBox) works with ItemsSource. ItemsControl use ItemContainerGenerator to populate its visual tree. Each item from ItemsSource wrap into container which derived from ContentControl. Then item is set as a Content, ItemTemplate is set as ContentTemplate and so on. When you put EditDeleteItem into ItemTemplate it becomes a part of visual tree but not an item. That's why there is no EditDeleteItem in e.NewItems and no subscription.
The right way is Commands, as you mentioned. You should declare two commands:
public class EditDeleteItem : UserControl
{
...
public static readonly RoutedUICommand EditCommand = new RoutedUICommand(...);
public static readonly RoutedUICommand DeleteCommand = new RoutedUICommand(...);
...
}
Now the part of template may look like:
<WrapPanel ...>
<Button ... Command="{x:Static EditDeleteItem.EditCommand}"/>
<Button ... Command="{x:Static EditDeleteItem.DeleteCommand}"/>
</WrapPanel>
Then you add command bindings to dCB_Props:
public partial class dCB_Props : UserControl
{
static dCB_Props()
{
...
CommandManager.RegisterClassCommandBinding(
typeof(dCB_Props),
new CommandBinding(EditDeleteItem.EditCommand, OnEditCommandExecuted));
CommandManager.RegisterClassCommandBinding(
typeof(dCB_Props),
new CommandBinding(EditDeleteItem.DeleteCommand, OnDeleteCommandExecuted));
...
}
...
}
You need to implement OnEditCommandExecuted and OnDeleteCommandExecuted in order to handle corresponding commands from EditDeleteItem.
I hope I understood your question correctly ;)

Categories

Resources