I have started learning WP 8.1 recently and run into an issue. I'm trying to "reimplement" some functions I found across applications. One of apps is able to change the InputScope after 6 letters have been written. You put your logon there which is built of 6 letters and 4 digits. The applications text box automagically changes scope after 6 letters have been input, changing the scope to numbers only.
<Grid>
<TextBox x:Name="TextBox1"
HorizontalAlignment="Left"
Margin="113,164,0,0"
TextWrapping="Wrap"
Text="TextBox"
InputScope="AlphanumericFullWidth"
VerticalAlignment="Top" TextChanged="TextBox1_TextChanged"/>
</Grid>
private void TextBox1_TextChanged(object sender, TextChangedEventArgs e)
{
TextBlock1.Text = TextBox1.Text.Length.ToString(); //Display length on string on textChanged, not important right now
if (TextBox1.Text.Length < 4) {
InputScope inputScope = new InputScope();
InputScopeName inputScopeName = new InputScopeName();
inputScopeName.NameValue = InputScopeNameValue.NumberFullWidth;
inputScope.Names.Add(inputScopeName);
TextBox1.InputScope = inputScope;
}
}
Please remember I'm beginner and could have made some awful and easy mistakes. I hope I can learn from you a bit :)
Related
I am developing a UWP app and I have to make a control like in the People app for Windows 10.
I am currently trying this
<StackPanel x:Name="stp">
<Button Content="Button 1" x:Name="btnAction1">
<Button.Flyout>
<MenuFlyout>
<MenuFlyoutItem Text="Action 1" Click="MenuFlyoutItem_Click">
</MenuFlyoutItem>
</MenuFlyout>
</Button.Flyout>
</Button>
</StackPanel>
and in c#
private void MenuFlyoutItem_Click(object sender, RoutedEventArgs e)
{
btnAction1.Margin = new Thickness(0, 10, 0, 0);
stp.Children.Add(new TextBox() { Name = "newTxtBox", Text="Tushar"});
}
But this will end up handling UI too much with no animation at all. I want to give an option to the user to remove this dynamically created control.
After that I would want something like this:Dynamically adding textboxes with animation and option to close
Can anybody please help?
Thanks in advance.
Check the documentation of Flyout and use the LightDismissOverlayMode property to suit your scenario. If any particular UI specific implementation required, post a screenshot.
I'm building a Windows Phone 8.1 Hub Application. One of the hub section contains a ListView that displays a list of articles. I'd like to add a Textblock to this hubsection which displays a message when the articles failed to download. The XAML Code is below:
<HubSection
x:Uid="ArticlesSection"
Header="ARTICLES"
DataContext="{Binding Articles}"
HeaderTemplate="{ThemeResource HubSectionHeaderTemplate}">
<DataTemplate>
<Grid>
<ListView
AutomationProperties.AutomationId="ItemListViewSection3"
AutomationProperties.Name="Items In Group"
SelectionMode="None"
IsItemClickEnabled="True"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource BannerBackgroundArticleTemplate}"
ItemClick="ItemView_ItemClick"
ContinuumNavigationTransitionInfo.ExitElementContainer="True">
</ListView>
<TextBlock
x:Name="NoArticlesTextBlock"
HorizontalAlignment="Center"
VerticalAlignment="center"
Style="{StaticResource HeaderTextBlockStyle}"
TextWrapping="WrapWholeWords"
TextAlignment="Center"/>
</Grid>
</DataTemplate>
</HubSection>
The problem I'm having is that I can't access the TextBlock from the C# code. Is there an easier way to do this?
The problem I'm having is that I can't access the TextBlock from the C# code.
Yes, since the TextBlock is defined inside a DataTemplate, the TextBlock won't be available until the DataTemplate has been applied. Thus, the x:Name attribute won't automatically generate a variable reference in the InitializeComponent method in your *.g.i.cs file. (Read up on XAML Namescopes for more information).
If you want to access it from your code-behind, there are two ways:
The first way is the simplest: you can get a reference to the TextBlock in the sender argument of the Loaded event handler for that TextBlock.
<TextBlock Loaded="NoArticlesTextBlock_Loaded" />
Then in your code-behind:
private TextBlock NoArticlesTextBlock;
private void NoArticlesTextBlock_Loaded(object sender, RoutedEventArgs e)
{
NoArticlesTextBlock = (TextBlock)sender;
}
The second way is to traverse the visual tree manually to locate the element with the required name. This is more suitable for dynamic layouts, or when you have a lot of controls you want to reference that doing the previous way would be too messy. You can achieve it like this:
<Page Loaded="Page_Loaded" ... />
Then in your code-behind:
static DependencyObject FindChildByName(DependencyObject from, string name)
{
int count = VisualTreeHelper.GetChildrenCount(from);
for (int i = 0; i < count; i++)
{
var child = VisualTreeHelper.GetChild(from, i);
if (child is FrameworkElement && ((FrameworkElement)child).Name == name)
return child;
var result = FindChildByName(child, name);
if (result != null)
return result;
}
return null;
}
private TextBlock NoArticlesTextBlock;
private void Page_Loaded(object sender, RoutedEventArgs e)
{
// Note: No need to start searching from the root (this), we can just start
// from the relevant HubSection or whatever. Make sure your TextBlock has
// x:Name="NoArticlesTextBlock" attribute in the XAML.
NoArticlesTextBlock = (TextBlock)FindChildByName(this, "NoArticlesTextBlock");
}
Jerry Nixon has a good page on his blog about this.
I would like to create something like CameraCaptureUI.CaptureFileAsync which will return the result to caller (location that user picked through bing maps in my case)
(the same question was asked here but I still need full screen UI or more complete code example)
Assuming the next use case:
CallerPage1 Navigate-> CallerPage2 (through Frame.Navigate(typeof(CallerPage2)) )
CallerPage2 Navigate-> LocationPickingPage (again through Frame.Navigate(typeof(LocationPickingPage )) <- here should be something else but not Frame.Navigate)
User picks a Location and presses done -> location object returned to CallerPage2
(through Frame.Navigate(typeof(CallerPage2)) )
And now if user presses back on CallerPage2 he/she will be navigated back to LocationPickingPage which is expected in navigation model described above but I wont to navigate him/her to CallerPage1
So this is how CameraCaptureUI.CaptureFileAsync behaves.
Maybe someone can help to look "behind the scenes" of CaptureFileAsync or familiar method and provide some example of how it can be implemented so that location picking can be performed like this:
Location location = await new LocationPickCaptureUI.CaptureLocationAsync();
Any help would be appreciated!
Edit
So, maybe someone can shad some light on how pages can share their data without affecting navigation history. I'm just looking for something like android's startActivityForResult.
I spend several days on this problem (msdn docs, researching different examples, forums and different sites including this one) and didn't find any approach so I think it is time to ask own question.
Sharing data between pages in manner I am looking for should be something obvious. Maybe I was looking in a wrong way but the problem is still persist's.
And please, if someone votes down my question share your mind and your source of knowledge as I still need help on this problem.
Thanks in advance
So, finally I've got an appropriate solution and maybe it can be helpful to anybody else.
The idea is to use Popup object and fit all the screen (however the details seemed like some kind of magic :) )
One thing: I used UserControl (in Visual Studio right click on project -> Add -> new item.. -> UserControl) template as in this scenario it is easy to manage popups's content
Here is the full source for C#:
CustomCaptureUI.xaml:
<UserControl
x:Class="Family.CustomCaptureUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Family"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
x:Name="Root">
<Grid>
<Border BorderBrush="Gray" BorderThickness="1">
<Grid x:Name="Panel" Background="Gray">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1" VerticalAlignment="Center">
<TextBlock Text="New text" Foreground="LightGray" FontSize="18"/>
<TextBox x:Name="ToDoText" Width="Auto" BorderBrush="Black" BorderThickness="1" VerticalAlignment="Center"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="SubmitButton" Background="Gray" Content="Submit" HorizontalAlignment="Center"/>
<Button x:Name="CancelButton" Background="Gray" Content="Cancel" HorizontalAlignment="Center"/>
</StackPanel>
</StackPanel>
</Grid>
</Border>
</Grid>
</UserControl>
CustomCaptureUI.xaml.cs:
public sealed partial class CustomCaptureUI : UserControl
{
public enum ResultStatuses
{
Canceled,
Ok,
None
}
public CustomCaptureUI()
{
_resultStatus = ResultStatuses.None;
// force content's size to preferable value
Root.Width = Window.Current.Bounds.Width;
Root.Height = Window.Current.Bounds.Width * 0.3;
// Init popup's Content
_popup.Child = this;
// Init popups's position
_popup.SetValue(Canvas.LeftProperty, (Window.Current.Bounds.Width - Root.Width) * 0.5);
_popup.SetValue(Canvas.TopProperty, (Window.Current.Bounds.Height - Root.Height) * 0.5);
}
public async Task<string> ShowDialog()
{
string result = string.Empty;
if (_semaphore != null) { DismissAddToDoPopup(); }
// Init a Task for block the ShowDialog-method until user presses Cancel or Submit
_semaphore = new Task(() => { });
CancelButton.Click += (sender, e) =>
{
_resultStatus = ResultStatuses.Canceled;
DismissAddToDoPopup();
};
SubmitButton.Click += (sender, e) =>
{
result = ToDoText.Text;
_resultStatus = ResultStatuses.Ok;
DismissAddToDoPopup();
};
ShowAddToDoPopup();
// actual blocking of ShowDialog
await _semaphore;
return result;
}
public void DismissDialog()
{
_resultStatus = ResultStatuses.Canceled;
DismissAddToDoPopup();
}
private void ShowAddToDoPopup()
{
ToDoText.Text = string.Empty;
_popup.IsOpen = true;
}
private void DismissAddToDoPopup()
{
if (_semaphore != null)
{
// starts the task and allows awaited ShowDialog-method to be released
// after _semaphore is finishing
_semaphore.Start();
_semaphore = null;
}
_popup.IsOpen = false;
}
public ResultStatuses ResultStatus
{
get { return _resultStatus; }
}
private Popup _popup = new Popup();
private Task _semaphore;
private ResultStatuses _resultStatus;
}
And then it can be used like this:
var dialog = new CustomCaptureUI();
string result = await dialog.ShowDialog();
if (dialog.ResultStatus == AddToDoDialog.ResultStatuses.Ok)
{
// Useful stuff
if (!string.IsNullOrWhiteSpace(result))
{
...
}
}
Hope it can save someone's time a little
I want to implement auto-complete on a textbox in a Windows 8 UI / Metro UI app using C#/XAML.
At the moment, when the soft / touch keyboard shows, it obscures the auto-complete box. However, on the text box focus, Windows 8 automatically scrolls the entire view up and ensures the text box is in focus.
In reality, all I want is the view to scroll up a little more (in fact, by the height of the auto-complete box).
I realise I can intercept the Showing event of InputPane.GetForCurrentView()
I can set InputPaneVisibilityEventArgs.EnsuredFocusedElementInView to true inside the Showing event fine (so Windows won't try to do anything).... however, how can I invoke the same scrolling functionality that Windows 8 would do, but ask it to scroll a little more!?
Here's the code for the main page:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,200,0,0">
<TextBlock HorizontalAlignment="Center" FontSize="60">App 1</TextBlock>
<TextBlock HorizontalAlignment="Center">Enter text below</TextBlock>
<TextBox HorizontalAlignment="Center" Margin="-10,0,10,0" Width="400" Height="30"/>
<ListBox HorizontalAlignment="Center" Width="400">
<ListBoxItem>Auto complete item 1</ListBoxItem>
<ListBoxItem>Auto complete item 2</ListBoxItem>
<ListBoxItem>Auto complete item 3</ListBoxItem>
<ListBoxItem>Auto complete item 4</ListBoxItem>
<ListBoxItem>Auto complete item 5</ListBoxItem>
</ListBox>
</StackPanel>
</Grid>
If you start up the simulator with the lowest resolution, use the hand to "touch" the textbox, this will bring up the soft keyboard. In the real app, the auto complete list will appear with items as the user enters text.
So in a nutshell, how can I move the screen up a bit more so the user can see the entire autocomplete list?
Bear in mind, in the real app, it'll be worse, as the user may not even notice the autocomplete list appearing "underneath" the keyboard.
I really would appreciate some advice, many thanks!
I have created an AutoCompleteBox for Windows Store apps, the nuget package is available at https://nuget.org/packages/AutoCompleteBoxWinRT
Ok, here is how I would tackle this since I cannot seem to find any way to control the scrolling of the app based on the appearance of the keyboard. I would create a user control that would form the basis for the auto-complete textbox.
<UserControl
x:Class="App6.MyUserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App6"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<TextBox x:Name="textBox" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" GotFocus="textBox_GotFocus" LostFocus="textBox_LostFocus" />
<ListBox x:Name="listBox" Height="150" Margin="0,-150,0,0" VerticalAlignment="Top" Visibility="Collapsed"/>
</Grid>
This is an incredibly basic implementation, so you will have to tweak to meet your needs.
Then, I would add the following code-behind to the user control
public sealed partial class MyUserControl1 : UserControl
{
// Rect occludedRect;
bool hasFocus = false;
public MyUserControl1()
{
this.InitializeComponent();
InputPane.GetForCurrentView().Showing += MyUserControl1_Showing;
}
void MyUserControl1_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
{
if (hasFocus)
{
var occludedRect = args.OccludedRect;
var element = textBox.TransformToVisual(null);
var point = element.TransformPoint(new Point(0, 0));
if (occludedRect.Top < point.Y + textBox.ActualHeight + listBox.ActualHeight)
{
listBox.Margin = new Thickness(0, -listBox.ActualHeight, 0, 0); // Draw above
}
else
{
listBox.Margin = new Thickness(0, textBox.ActualHeight, 0, 0); // draw below
}
}
}
private void textBox_GotFocus(object sender, RoutedEventArgs e)
{
listBox.Visibility = Windows.UI.Xaml.Visibility.Visible;
hasFocus = true;
}
private void textBox_LostFocus(object sender, RoutedEventArgs e)
{
listBox.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
hasFocus = false;
}
}
Next steps would be to expose properties to pass data to be bound to the ListBox. Hard core would be ListBoxItem templating and more, depending on how reusable you wanted it to be.
I've run out of ideas trying to collapse a DataGridTextcolumn depending on a value set in a public property (in a WPF/XAML/MVVM Light application).
An extract of the xaml is:
<StackPanel>
<DataGrid AutoGenerateColumns="False" Name="PipelinesGrid"
HorizontalAlignment="Left"
ItemsSource="{Binding Pipelines}"
SelectedItem="{Binding SelectedPipelineView, Mode=TwoWay}"
VerticalAlignment="Top" Margin="10,16,0,0"
SelectionUnit="FullRow" SelectionMode="Single"
CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding DailyCapacity, Mode=TwoWay}"
Header="Capacity(d)"
Visibility="{Binding Source={x:Reference PipelinesGrid},
Path=DataContext.ShowCapacities}"/>
Here is the Visibility setting is one of many that I've tried (this one gives a cycylical dependency error).
A relevant extract of the ViewModel code is:
private string _showCapacities;
public string ShowCapacities
{
get { return _showCapacities; }
set { _showCapacities = value; RaisePropertyChanged("ShowCapacities"); }
}
private void OnProjectSelected(ProjectSelectedArgs obj)
{
_selectedProject = obj.SelectedProject;
if (_selectedProject != null)
{
Pipelines = new ObservableCollection<PipelineView>();
foreach (var projectPipeline in _selectedProject.ProjectPipelines)
{
Pipelines.Add(new PipelineView(projectPipeline));
}
switch (_selectedProject.ProjectCategory.ProjectCategory1)
{
case "Upstream":
ShowCapacities = "Collapsed";
break;
case "Mid-Stream":
ShowCapacities = "Visible";
break;
}
}
IsEditing = false;
}
I've been informed by this article (http://stackoverflow.com/questions/8847661/datagridtextcolumn-visibility-binding) that I needed to use Source and Xreference. Thanks for any help.
There are various articles on SO that discuss this problem. Search for "wpf visibility binding datagrid column".
The problem is because DataGrid columns don't belong to the visual or logical tree of the DataGrid, so WPF can't find a suitable DataContext. Trying to use a relative or element binding fails as well.
Needless to say, some clever people have already solved this issue. My favourite solution is the proxy freezable method explained here: http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/ which worked fine for me.