WPF: Can I show one double in two different ways? [duplicate] - c#

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

C# WPF XAML , How create Textbox input field with stringformat?

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

Getting selected item in ListView without selecting an Item on UI

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.

How to use a Popup binded to a ToggleButton inside a ListView in xaml wpf?

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.

Formatting of text in a textblock in windows phone 7

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

Data binding in pivot TitleTemplate for Windows Phone

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>

Categories