This question already has answers here:
Rounding a Value in the WPF Binding
(3 answers)
Closed 2 years ago.
I am creating a "Progress-Bar-Clock", where the Time gets shown as percentages. For example, this is the time right now:
Xaml:
<Viewbox>
<Grid>
<Grid.DataContext>
<vm:TimerVM/>
</Grid.DataContext>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,10,10,10">
<Border BorderBrush="Gray" BorderThickness="1">
<Label Content="Progress Bar Timer" FontFamily="Bold" FontSize="45" HorizontalAlignment="Center" HorizontalContentAlignment="Center" Margin="0,0,0,20"/>
</Border>
<StackPanel>
<Label Content="Seconds in this Minute:"/>
<Grid Width="400" Height="25">
<ProgressBar Value="{Binding SecondsInMinute}" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<Run Text="{Binding SecondsInMinute}"/><Run Text="%"/>
</TextBlock>
</Grid>
</StackPanel>
<StackPanel>
<Label Content="Minutes in this hour:"/>
<Grid Width="400" Height="25">
<ProgressBar Value="{Binding MinutesInHour}" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<Run Text="{Binding MinutesInHour}"/><Run Text="%"/>
</TextBlock>
</Grid>
</StackPanel>
<StackPanel>
<Label Content="Hours in this day:"/>
<Grid Width="400" Height="25">
<ProgressBar Value="{Binding HoursInDay}" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<Run Text="{Binding HoursInDay}"/><Run Text="%"/>
</TextBlock>
</Grid>
</StackPanel>
<StackPanel Margin="0,50,0,0">
<Label Content="Time until timer finished:"/>
<Grid Width="400" Height="25">
<ProgressBar Value="{Binding TimerInPercent}" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<Run Text="{Binding TimerInPercent}"/><Run Text="%"/>
</TextBlock>
</Grid>
</StackPanel>
</StackPanel>
</Grid>
</Viewbox>
The thing that disturbs me is the percentage. At the moment I show it with only two digits, so it's easier to read, but that also affects the progress bar.
This is the method, my second thread executes to update the timer:
private void UpdateRelative()
{
while (true)
{
DateTime time = DateTime.Now;
SecondsInMinute = Math.Round(time.Second / 0.6);
MinutesInHour = Math.Round(time.Minute / 0.6);
HoursInDay = Math.Round(time.Hour / 0.24);
Thread.Sleep(timeout);
}
}
I would like to use a non-rounded up number for the progress bar, but a rounded one for the text on the progress bar. Is that possible without creating a second property that the label would use?
You could format the displayed value in the view instead of rounding the actual value:
<Run Text="{Binding MinutesInHour, StringFormat=N0}"/><Run Text="%"/>
Code:
MinutesInHour = time.Minute / 0.6;
Related
Code XAML
<Grid>
<StackPanel Orientation="Horizontal">
<Label Content="Bank Doc Nbr :" Margin="0,0,0,0" VerticalAlignment="Center" />
<TextBox Name="txtBankNbr" Text="{Binding ElementName=txtBankNbr, Path=Text, StringFormat={}{0:##0/000}}" materialDesign:HintAssist.Hint="0/000" VerticalAlignment="Center" materialDesign:TextFieldAssist.DecorationVisibility="Hidden" BorderThickness="0" />
<Label Content="Bank Income :€" Margin="5,0,0,0" VerticalAlignment="Center" />
<TextBox Name="txtBankIncome" Text="{Binding ElementName=txtBankIncome, Path=Text,StringFormat={}{0:######0.00}}" materialDesign:HintAssist.Hint="0,00" VerticalAlignment="Center" materialDesign:TextFieldAssist.DecorationVisibility="Hidden" BorderThickness="0" />
</StackPanel>
</Grid>
------ Explanation: Format of txtBankNbr is {0:##0/000} and can only receive numbers. eg "1/001" , 12/021 , ....
Format of txtBankNbr is {0:##0.00} and can only receive a decimal
number What is wrong in my code?
Thanks
Try this:
StringFormat={}{0:#.##}
it should show two decimal place
I'm working on a WPF application where I've made a ListView on UI which is two-way binding enabled. This WPF application is being developed for a windows 10 based smartphone. So whenever a user taps an item in the list whose data source is data-binded to back data collection, I've to do some operation for that item in code behind.
Now the problem is, I always receive a null object from the below function whenever the user taps on the item.
CartItem selectedItem = (CartItem)lv_CartItems.SelectedItem;
I only get a filled item object when the user actually selects an item by clicking on ListViewItem rather than tapping on it.
I want to get the selected item when the user taps on it. Is there any workaround available in WPF this problem? I've stuck here
My ListViewItem template looks like this.
<ListView Name="lv_CartItems" Loaded="lv_CartItems_Loaded"
HorizontalAlignment="Center" ScrollViewer.CanContentScroll="False"
ScrollViewer.VerticalScrollBarVisibility="Visible"
Width="250" Height="230" SelectionMode="Single"
>
<ListView.ItemTemplate>
<DataTemplate>
<Viewbox>
<Grid Width="230" Height="110" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width=".1*" />
<ColumnDefinition />
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border BorderBrush="LightGray" BorderThickness="1"
Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="6" Grid.RowSpan="3" >
</Border>
<Viewbox Grid.Row="0" >
<Image Name="img_ItemImage"
Source="{Binding Image, Mode=TwoWay }"
Width="20" Height=" 25" />
</Viewbox>
<Viewbox Grid.Column="2" Grid.ColumnSpan="3" VerticalAlignment="Top" >
<TextBlock Name="lbl_ItemName" TextWrapping="Wrap" Width="180" Foreground="Gray"
Text="{Binding Name , Mode=TwoWay }" >
</TextBlock>
</Viewbox>
<Viewbox Grid.Row="1" Margin="10,0" VerticalAlignment="Top" >
<TextBlock Foreground="Gray" >Qty:</TextBlock>
</Viewbox>
<Viewbox Grid.Row="2" Margin="0,0" VerticalAlignment="Top" >
<StackPanel Orientation="Horizontal" >
<Button Name="btn_Minus" FontWeight="ExtraBold" Tag="{Binding SKU_No,Mode=TwoWay}" Padding="0" Width="12"
Resources="{StaticResource cartitembutton}" Click="btn_Minus_Click" >
<Image Source="/Resources\Icons\minus.png" ></Image>
</Button>
<Border BorderThickness="1" Margin="2,0" Width="13" CornerRadius="2" BorderBrush="LightGray" >
<TextBlock Name="lbl_Quantity" FontWeight="Bold" Foreground="Gray"
HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Quantity , Mode=TwoWay }" >
</TextBlock>
</Border>
<Button Name="btn_Increment" FontWeight="ExtraBold" Width="12"
Resources="{StaticResource cartitembutton}" Tag="{Binding SKU_No,Mode=TwoWay}"
Padding="0"
Click="btn_Increment_Click">
<Image Source="/Resources\Icons\union_10.png" ></Image>
</Button>
</StackPanel>
</Viewbox>
<Viewbox Grid.Row="1" Grid.Column="2" Margin="5,0"
HorizontalAlignment="Left" Grid.ColumnSpan="3" >
<TextBlock Name="lbl_Price" FontWeight="DemiBold"
Text="{Binding Price , Mode=TwoWay}" ></TextBlock>
</Viewbox>
<Viewbox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="3"
VerticalAlignment="Top" Margin="0,0" >
<TextBlock Name="lbl_Appearence"
Text="{Binding Appearance , Mode=TwoWay }"
TextWrapping="Wrap" Foreground="Gray" Width="210" >
</TextBlock>
</Viewbox>
<Viewbox Grid.Column="5" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="2,2"
>
<Button Name="btn_DeleteItem"
Click="btn_DeleteItem_Click"
Resources="{StaticResource cartitembutton}" >
<Image Source="/Resources/Icons/delete.png" ></Image>
</Button>
</Viewbox>
</Grid>
</Viewbox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This is how a listVeiw looks like.
You don't actually want the selected item, you want to know which item contained the button that was clicked- whether that item is selected or not.
You can do this with events, but the more "correct" way to do it in WPF is with commands.
Commands are a pattern which separate the logic of an action (e.g. deleting an item) from the visual component that triggers the action (e.g. the button the user clicks). A command includes a parameter, which you can use to specify which item the command is being executed on. There are a couple different types on commands in WPF, but I'll be explaining using RoutedCommand.
In your case you'd first declare your command(s) in your Window:
public static readonly RoutedCommand DeleteItemCommand =
new RoutedCommand("DeleteItem", typeof(MainWindow));
private void OnCanExecuteDeleteItem(object sender , CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter != null;
}
private void OnExecuteDeleteItem(object sender, ExecutedRoutedEventArgs e)
{
SomeType item = (SomeType)e.Parameter;
//Actually delete the item
}
And you'd add a CommandBinding to your Window which links the command to the methods which handle it:
<Window.CommandBindings>
<CommandBinding Command="local:MainWindow.DeleteItemCommand" CanExecute="OnCanExecuteDeleteItem" Executed="OnExecuteDeleteItem"/>
</Window.CommandBindings>
And finally, to link your delete Button to the command:
<Button Name="btn_DeleteItem" Resources="{StaticResource cartitembutton}" Command="local:MainWindow.DeleteItemCommand" CommandParameter="{Binding}">
<Image Source="/Resources/Icons/delete.png"/>
</Button>
CommandParameter="{Binding}" works because your Button is inside a DataTemplate, so its DataContext will be the item that is being displayed. This lets you check e.Parameter in your routed event methods to see which item is being interacted with.
I want to make a list of ToggleButtons. Each of them is binded to a popup.
I had a problem with that, so I tried to put everything inside a StackPanel.
But, now, when the app is running, it shows an empty space (for the Popup) right after the ToggleButton. What can I do to solve that?
I've just added two images:
The first one is when the page is being uploaded.
The second one is when I scroll down the page.
<ListView x:Name="ListOfRecipes" HorizontalAlignment="Center" VerticalAlignment="Top" ItemsSource="{Binding}" Grid.Row="1" Margin="25,0.333,25,35" ScrollViewer.VerticalScrollMode="Enabled" Grid.RowSpan="5" >
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<ToggleButton x:Name="RecipeButton" Grid.Row="1" BorderBrush="#FF65C365" VerticalAlignment="Center" HorizontalAlignment="Center" Click="Button_Click" Height="150" Width="328" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Height="128" Width="328">
<Image Source="{Binding Path=ImageUri}" Height="128" Width="128" Margin="0,6,0,-5.667" />
<StackPanel Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Top" Height="128" Width="192">
<TextBlock Height="25" Width="190" Foreground="#FF6FDC13" Text="{Binding Name}" VerticalAlignment="Top" />
<Image Name="YesOrNoImage" Source="{Binding Path=YesOrNoImage}" Width="102" Height="102" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</StackPanel>
</StackPanel>
</ToggleButton>
<Popup IsOpen="{Binding IsChecked, ElementName=RecipeButton, Mode=TwoWay}" Height="514" Width="328" VerticalAlignment="Center" Name="PopupOne" Grid.Row="1" Grid.RowSpan="4" IsLightDismissEnabled="True" IsHoldingEnabled="False" ScrollViewer.VerticalScrollMode="Enabled" >
<Border BorderBrush="#FF65C365" BorderThickness="1" Background="White" Height="514" Width="328">
<StackPanel Orientation="Vertical" ScrollViewer.VerticalScrollMode="Enabled">
<Image Source="{Binding Path=ImageUri}" Height="328" Width="328" />
<TextBlock Foreground="#FF6FDC13" Text="{Binding Name}" HorizontalAlignment="Left" FontSize="28" />
<ScrollViewer VerticalScrollMode="Enabled" >
<TextBlock Foreground="Black" Text="{Binding RecipeText}" HorizontalAlignment="Left" FontSize="18" />
</ScrollViewer>
</StackPanel>
</Border>
</Popup>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
It seems that the issue is caused by the <PopUp Height=514/>
To test it, set the height to 0 to see if it fixes the gap. If so, you can bind the visibility to PopUp.IsOpen using a Visibility converter (I think Blue MVVM has one). Since I'm not very educated on Converters at the moment, I came up with a workaround.
public RecipeButton : INotifyPropertyChanged {
// Need to implement INotifyPropertyChanged logic on IsCheckedVisiblity for UI to be notified of visibility changes
public Visibility IsCheckedVisibility { get; set; }
private bool _IsChecked;
public bool IsChecked {
get { return _IsChecked };
set { _IsChecked = value;
this.IsCheckedVisibility = value == true ? Visiblity.Collapsed : Visiblity.Visible;
}
}
<PopUp Visibility = "{Binding IsCheckedVisibility}"/>
Let me know if that doesn't work and I'll try something else.
I am have a text which is has bold, underline and italic html characters. For example
<b> hello<b> how are <i>you</i>. I am <u>fine</u>
I have to show it in formatted form in a textblock on WP7. I have a listbox like this
<ListBox x:Name="LBayaDetail" Loaded="LBayaDetail_Loaded" Margin="6,0,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="ayaContent" Margin="0,6,0,0" Hold="ayaContent_Hold" Tap="ayaContent_Tap" Loaded="ayaContent_Loaded" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="6"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition Width="6" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Background="#FFC5AC88" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock x:Name="ayaIndex" Text="{Binding aya}" FontSize="36" Margin="0" FontWeight="Bold" HorizontalAlignment="Center" />
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Center">
<Image Source="{Binding BookmarkImage}" HorizontalAlignment="Center" Width="48" Height="48" Margin="0,0,0,12" />
<Image Source="{Binding NoteImage}" HorizontalAlignment="Center" Width="48" Height="48" Margin="0,0,0,12" />
<Image Source="{Binding TagImage}" HorizontalAlignment="Center" Width="48" Height="48" Margin="0,0,0,12" />
</StackPanel>
</Grid>
<Grid Grid.Row="1" Background="#FFC5AC88" x:Name="Media" Tap="Media_Tap" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image Source="/Images/Media-Play(1).png" Width="30" Height="30" HorizontalAlignment="Center" Margin="12,0,0,0" VerticalAlignment="Top" />
</Grid>
<!--ini pak dimana tempat untuk ayat dan translasi-->
<Grid Grid.Column="2" Background="#FFAC9574" Margin="6,0,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock x:Name="aya" TextWrapping="Wrap" Text="{Binding text}" HorizontalAlignment="Right" FontFamily="/Fonts/me_quran2.ttf#me_quran2" FontSize="{Binding FontSizeAya}" Foreground="Black" Margin="24,0,12,-12" TextAlignment="Right" Visibility="{Binding visibility1}" />
</Grid>
<Grid Grid.Column="2" Grid.Row="1" Margin="6,0,0,0" Background="#FFAC9574" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel>
<TextBlock Visibility="{Binding visibility2}" x:Name="translation" Text="{Binding translation}" TextWrapping="Wrap" HorizontalAlignment="Right" FontFamily="/Fonts/ARIALUNI.TTF#Arial Unicode MS" FontSize="{Binding FontSizeTranslation}" Foreground="#FF5D2A07" Margin="12,6,6,0" />
<TextBlock Visibility="{Binding visibility3}" x:Name="translation2" Text="{Binding translation2}" TextWrapping="Wrap" HorizontalAlignment="Right" FontFamily="/Fonts/ARIALUNI.TTF#Arial Unicode MS" FontSize="{Binding FontSizeTranslation}" Foreground="DarkGreen" Margin="12,20,6,0" />
</StackPanel>
</Grid>
<!-- -->
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I fetch from database like
App.Listxyz = (Application.Current as App).db.SelectList<Aya>(strSelect);
And assign it to Listbox like this
LBayaDetail.ItemsSource = App.ListAyaBySurah;
And shows the text as it is and do not format it which is obvious. I searched for it and I was able to format individual textblock by using "RUN" but I am unable to do it in listbox.
I also tried to use HTMLTextBlock but it also doesn't format the text and shows it like this
Hi
How
Are
You
Any help will be much appreciated that how do I format a textblock with different text decorations.
Thanks
You should place a grid and a stackpanel inside the listbox. Something like the following
<Grid>
<StackPanel Grid.Column="1">
<TextBlock Padding="0,5,0,2" TextWrapping="Wrap">
<Run Text="{Binding test}" FontWeight="Bold" /> <Run Text="{Binding test2}" />
<LineBreak/>
<Run Text="{Binding test3}" />
</TextBlock>
</StackPanel>
</Grid>
One way to do that is:
public class FormattedText
{
public string Text { get; set; }
public bool IsBold { get; set; }
public bool IsItalic { get; set; }
public bool IsUnderlined { get; set; }
}
Have a method that converts the HTML you stored in your db to a list of the class you have above
example:
From this:
<b> hello<b> how are <i>you</i>. I am <u>fine</u>
to this:
First element:
Text = "hello"
IsBold = true
skip what not needed since bool default value is false
Second element
Text =" how are"
skip what not needed since bool default value is false
Third item
Text ="you"
IsItalic=true;
skip what not needed since bool default value is false
and so on....
and then have another method that from that list creates a list of Runs to be added to your TextBlock or
maybe create a custom TextBlock witch take the List<FormattedText> from DataContext and process it by adding the Run elements to self
I must be missing something simple here...I am writing a Windows Phone 7 app and I have customized my pivot header to be the following:
<controls:Pivot Name="InfoPivot">
<controls:Pivot.TitleTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,0,0,0" VerticalAlignment="Top">
<Rectangle Fill="{Binding CategoryFill}" Height="50" Width="50" Margin="355,25,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Name="CategoryRect" />
<StackPanel Margin="-425,-14,0,0" Width="432">
<TextBlock x:Name="StationTitle" Text="{Binding StationTitle}" Margin="10,0,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
<TextBlock Name="LocationTitle" Text="{Binding LocationTitle}" TextWrapping="Wrap" Margin="12,0,0,20" Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</controls:Pivot.TitleTemplate>
When I navigate to this page, I pass Station and Location as parameters, and in the OnNavigatedTo() for this page I try to set the StationTitle and LocationTitle. Unfortunately, I end up getting:
Error 2 The name 'StationTitle' does not exist in the current context
How should/do we go about accessing members in the Pivot TitleTemplate? Any help will be appreciated! Thanks.
Stop using the title template and binding to acheive this. Try this instead:-
<controls:Pivot Name="InfoPivot">
<controls:Pivot.Title>
<StackPanel Orientation="Horizontal" Margin="0,0,0,0" VerticalAlignment="Top">
<Rectangle Fill="{Binding CategoryFill}" Height="50" Width="50" Margin="355,25,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Name="CategoryRect" />
<StackPanel Margin="-425,-14,0,0" Width="432">
<TextBlock x:Name="StationTitle" Margin="10,0,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
<TextBlock x:Name="LocationTitle" TextWrapping="Wrap" Margin="12,0,0,20" Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
</StackPanel>
</controls:Pivot.Title>
Then in code-behind:-
if (NavigationContext.QueryString.TryGetValue("Station", out station))
{
StationTitle.Text = station;
}
if (NavigationContext.QueryString.TryGetValue("LocationTitle", out locationTitle))
{
LocationTitle.Text = locationTitle;
}
Without seeing all of your code, this may be as simple as making the Name declaration consistent on your two TextBlocks.
Note, one is Name="", the other is x:Name="".
Defining the template inline worked for me, The TitleTemplate just wouldn't work.
<phone:Pivot>
<phone:Pivot.Title>
<TextBlock Margin="0"
Text="{Binding Exercise.Name}"
Style="{StaticResource MainTitleStyle}"/>
</phone:Pivot.Title>
</phone:Pivot>