update 9/17/2012: restated the question and added recreation steps
I'm trying to add a WrapGrid style image gallery to an ItemDetailPage. So far the only solution I've found to achieve this is to create group styles and use a DataTemplate selector. This seems like overkill to do this on a detail page as I would need to create a class for every column on my page.
I attempted to solve this as shown below but GridView scrolls independently of my ScrollViewer which is unacceptable.
To recreate start with the default Grid application in VS:
Add this property to SampleDataItem
// Add to SampleDataItem TODO: replace int with image url strings
private List<int> _subItems = null;
public List<int> SubItems
{
get
{
if (_subItems == null)
{
_subItems = new List<int>();
for (int i = 0; i < 50; i++)
this._subItems.Add(i);
}
return this._subItems;
}
set { this.SetProperty(ref this._subItems, value); }
}
in ItemDetailPage.xaml replace the RichTextColumns in the ScrollViewer:
<!--Fixed column layout, replaces RichTextColumns from template-->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="800"/>
<ColumnDefinition Width="1400"/>
</Grid.ColumnDefinitions>
<StackPanel>
<TextBlock Text="{Binding Title}"/>
<Image x:Name="image" MaxHeight="480" Margin="0,20,0,10" Stretch="Uniform" Source="{Binding Image}"/>
</StackPanel>
<GridView ScrollViewer.HorizontalScrollMode="Disabled" VerticalAlignment="Top" ItemsSource="{Binding SubItems}" Grid.Column="1" ItemTemplate="{StaticResource GridViewDataTemplate1}" >
</GridView>
</Grid>
Finally add the following DataTemplate
<DataTemplate x:Key="GridViewDataTemplate1">
<Grid Background="Yellow" Width="200" Height="200"/>
</DataTemplate>
You can achieve this by setting the HorizontalScrollMode of the GridView to Disabled
<GridView ScrollViewer.HorizontalScrollMode="Disabled" />
However, I would urge you to think about the best approach here. If the GridViews are not related to each, show them on separate pages. If they are related, then group one GridView. You can style the items of the groups differently using a DataTemplateSelector.
Related
I am having a hard time understanding how to properly use Material UI's flexbox integeration:
This way I can align the items the way I want:
export default function Home() {
return (
<Grid container justify={"space-between"}>
<Grid item>
<Typography>Left text</Typography>
</Grid>
<Grid item>
<Typography>Right text</Typography>
</Grid>
</Grid>
);
}
But I'd expect that this should work, too:
export default function Home() {
return (
<Grid container>
<Grid item xs={6} justify={"flex-start"}>
<Typography>Left text</Typography>
</Grid>
<Grid item xs={6} justify={"flex-end"}>
<Typography>Right text</Typography>
</Grid>
</Grid>
);
}
But the latter has not the desired outcome. What am I missing here?
Without defining Typography component type, it'll spawn <p> tag, which is of block type.
You can find it in the docs: https://material-ui.com/api/typography/
Therefore, you did align something right, but that "something" takes whole 6 columns. Text is not aligned, its heading tag is.
You should try this on "Right text" Typography component:
<Typography align="right">Righttext</Typography>
EDIT: You can also add container prop to Grid component. This way, justify property will be available to you:
<Grid item container xs={6} justify={"flex-end"}>
<Typography>Right text</Typography>
</Grid>
When you add container prop to Grid component, children of that component become flex elements. Then you don't have to know which tags each Material component spawns when component is rendered.
You can check this behavior in this example of Material docs:
https://material-ui.com/components/grid/#nested-grid
I want to change the orientation property like the following below:
<Style x:Key="FlipViewStyleV" TargetType="FlipView">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel AreScrollSnapPointsRegular="True" Orientation="Vertical" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
And I want to let it worked when the device orientation changed, the orientation property should also follow the change. But it does not worked when I add a button in the code-behind to change the orientation from vertical to horizontal, does some one know?
Looks like changing the Orientation property of a FlipView's ItemsPanel doesn't work for some reason. So here's an alternative.
You will need to duplicate your FlipView. One would implement a Vertical VirtualizingStackPanel and the other a Horizontal VirtualizingStackPanel.
Define them in your page's Resources.
<Page.Resources>
<ItemsPanelTemplate x:Key="HorizontalItemsPanel">
<VirtualizingStackPanel AreScrollSnapPointsRegular="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="VerticalItemsPanel">
<VirtualizingStackPanel AreScrollSnapPointsRegular="True" Orientation="Vertical" />
</ItemsPanelTemplate>
</Page.Resources>
Then, you will want to use SimpleOrientationSensor to monitor the phone's orientation changes.
private SimpleOrientationSensor _orientationSensor = SimpleOrientationSensor.GetDefault();
After you have subscribed to its OrientationChanged event,
_orientationSensor.OrientationChanged += OrientationSensor_OrientationChanged;
in its callback, simply hide and show the FlipViews accordingly.
private async void OrientationSensor_OrientationChanged(SimpleOrientationSensor sender, SimpleOrientationSensorOrientationChangedEventArgs args)
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
switch (args.Orientation)
{
case SimpleOrientation.NotRotated:
case SimpleOrientation.Rotated180DegreesCounterclockwise:
this.HorizontalFlipView.Visibility = Visibility.Visible;
this.VerticalFlipView.Visibility = Visibility.Collapsed;
break;
case SimpleOrientation.Rotated90DegreesCounterclockwise:
case SimpleOrientation.Rotated270DegreesCounterclockwise:
this.HorizontalFlipView.Visibility = Visibility.Collapsed;
this.VerticalFlipView.Visibility = Visibility.Visible;
break;
}
});
}
The E-mail application in Windows 8.1 has a nice animation in the AppBar. When a button is not enabled the button disappears and the buttons that are left moves to fill empty space. This happens if several E-mails are selected in the application.
What should I do to add this in my application?
Edit: Below is the animation I’m talking about. The second button from the right is no longer available so it shrinks and then the other buttons is moved to the empty space.
The AppBar control uses StackPanel control for the grid in it. So when a button added, it automatically repositions all the other buttons. Well, even though I don't know how the E-Mail app does the animation you posted, I definitely can show you the way for it. Hope it does give an idea.
Here is the XAML of the AppBar:
<Page.BottomAppBar >
<AppBar IsSticky="True" Name="AppBar" IsOpen="True" FlowDirection="RightToLeft">
<StackPanel Name="bottomAppBar" Orientation="Horizontal" >
<AppBarButton Name="btnOptions" Icon="Setting" Width="100" Label="Options" />
<AppBarButton Name="btnHelp" Icon="Help" Width="100" Label="Help" />
<AppBarButton Name="btnExit" Icon="Import" Width="100" Label="Exit" />
</StackPanel>
</AppBar>
</Page.BottomAppBar>
Assuming you have a button that hides the button you don't want. Let's say btnHelp in this case.
The button should be like this:
<Button Content="Button" HorizontalAlignment="Left" Margin="170,79,0,0"
VerticalAlignment="Top" Height="66" Width="131" Click="Hide_Help_Click"/>
So the click event should be like this
private async void Hide_Help_Click(object sender, RoutedEventArgs e)
{
while (true)
{
await Task.Delay(1);
if( btn.Width > 0 )
{
btnHelp.Width = btnHelp.Width - 2;
}
else
{
break;
}
}
btnHelp.Visibility = Visibility.Collapsed;
}
This way, it's like the exit button goes out on top of the Help button, so maybe it's a little ugly, but this works like what you need. So a little change and maybe some animation you add, it should exactly do the same what you have posted.
I am new in Windows Phone.
In my app I have a textbox where cursor will continuously blink for input at first. I have a custom dialpad to take input from users. So I have to disable the Windows Phone Keyboard.
After searching online, most of the solution is based on removing the focus from textbox to hide the keyboard.
In my case, its not happening since keyboard pops up and hide instantly.
Any help would be highly appreciated.
Another thing: I also need the cursor to be blinking in textbox.
May this will help you, create GotFocus event of your textbox.
GotFocus="input_GotFocus"
private void input_GotFocus(object sender, RoutedEventArgs e)
{
this.Focus();
}
One workaround could be to not use TextBox at all. Instead, you can use a simple TextBlock and on tap on the TextBlock, open your custom keypad. You can probably toggle visibility of the keypad to hide/unhide it. on key press of the keypad, update the text of the TextBlock.
EDIT : Adding a sample code for this (with cursor implementation as well)
Xaml for my custom TextBox implementation :
<Border x:Name="brdTextBox" Background="White" BorderBrush="Blue" HorizontalAlignment="Stretch" Height="100"
Margin="10">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="txtEnterText" FontSize="28" Foreground="Black" Margin="0"></TextBlock>
<TextBlock x:Name="txtCursor" FontSize="28" Foreground="Black" Text="|" Margin="0"></TextBlock>
</StackPanel>
</Border>
A sample code behind, that uses timer to control the tick of the cursor :
Timer timer = new Timer((obj) =>
{
Dispatcher pageDispatcher = obj as Dispatcher;
pageDispatcher.BeginInvoke(() =>
{
if (txtCursor.Text == "|")
{
txtCursor.Text = "";
}
else
{
txtCursor.Text = "|";
}
});
}, this.Dispatcher, 1000, 1000);
After this, you can probably bring up your keypad on border tap, and on key event of the keypad, fill up the textblock. You can tweak the timer duration and intervals to achieve a close resemblance to the actual cursor.
Hope it helps.
I'm struggling with touch support in WinRT.
I have a Canvas with a Frame that contains a TextBlock. The TextBlock can have varying amounts of text which could make the Frame extend below the bottom of the Canvas. If that happens, I want the user to be able to touch the Frame and move it up so they can finish reading the text. If they move the Frame all the way up, it should stop when the bottom of the Frame is a set margin from the bottom of the Canvas. Same for moving it back down. Using the Inertia capabilities would be preferred as well.
If anyone can offer some direction, I'd appreciate it.
I would recommend wrapping a ScrollViewer around your textblock enabling the user to scroll on the screen to see all the text.
<ScrollViewer>
<TextBlock Content="Very long content goes here" />
</ScrollViewer>
For additional information check these sites out:
Link to the scrollviewer in the control list
Link to the scrollviewer documentation
I figured it out...
<Canvas x:Name="MainCanvas" ManipulationMode="TranslateRailsX" IsRightTapEnabled="False" IsDoubleTapEnabled="False" Margin="50,50,716,0" Width="600" ManipulationDelta="MainFrame_ManipulationDelta_1">
<Canvas.RenderTransform>
<CompositeTransform x:Name="ScrollMain"></CompositeTransform>
</Canvas.RenderTransform>
<Frame x:Name="MainFrame" Background="Beige" Height="auto" Width="600">
<RichTextBlock x:Name="MainContent" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="18" FontFamily="Segoe Script" Width="540" HorizontalAlignment="Left" Margin="30,10,0,10" Foreground="Black" Height="auto" IsDoubleTapEnabled="False" IsHoldingEnabled="False" IsRightTapEnabled="False" IsTapEnabled="False" ManipulationMode="None" IsTextSelectionEnabled="False"/>
</Frame>
</Canvas>
MainCanvas.ManipulationMode = ManipulationModes.TranslateY | ManipulationModes.TranslateRailsY | ManipulationModes.TranslateInertia;
private void MainFrame_ManipulationDelta_1(object sender, ManipulationDeltaRoutedEventArgs e)
{
CompositeTransform transform = ScrollMain as CompositeTransform;
double yDelta = e.Delta.Translation.Y;
double bDelta = (MainFrame.ActualHeight - pageRoot.ActualHeight + MainCanvas.Margin.Top + MainCanvas.Margin.Top) * -1;
if (transform.TranslateY + yDelta > 0)
{
yDelta = transform.TranslateY * -1;
}
if (transform.TranslateY + yDelta < bDelta)
{
transform.TranslateY = bDelta;
}
else
{
transform.TranslateY += yDelta;
}
base.OnManipulationDelta(e);
}