I am developing a UWP app where there is a "page" and in that page, there are several "textbox"es which values are entered by a user (numbers). When it is navigated to other pages to take other values and came back to this page the values entered in "textbox"es are all lost. I used "NavigationCacheMode", no success.
Could you please help how to maintain values in UI elements (textboxes) in current page when navigating to other pages.
I would appreciate if the solution were in VB.NET.
Thank you very much.
You would have to save the date by yourself in this scenario. For example, you could choose the ApplicationData.LocalSettings to save the data when navigating to other page.
You could save the data on the page's OnNavigatedFrom method and get the data in its OnNavigatedTo method like the following:
<StackPanel>
<TextBox x:Name="textbox1"></TextBox>
<TextBox x:Name="textbox2"></TextBox>
<Button Content="navigate" Click="Button_Click"></Button>
</StackPanel>
Public NotInheritable Class MainPage
Inherits Page
Dim localSettings As Windows.Storage.ApplicationDataContainer = Windows.Storage.ApplicationData.Current.LocalSettings
Protected Overrides Sub OnNavigatedTo(e As NavigationEventArgs)
MyBase.OnNavigatedTo(e)
Dim value1 As Object = localSettings.Values(textbox1.Name)
Dim value2 As Object = localSettings.Values(textbox2.Name)
If value1 IsNot Nothing And value2 IsNot Nothing Then
textbox1.Text = value1.ToString()
textbox2.Text = value2.ToString()
End If
End Sub
Protected Overrides Sub OnNavigatedFrom(e As NavigationEventArgs)
MyBase.OnNavigatedFrom(e)
localSettings.Values(textbox1.Name) = textbox1.Text
localSettings.Values(textbox2.Name) = textbox2.Text
End Sub
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Frame.Navigate(GetType(BlankPage1))
End Sub
End Class
Related
I'm building a form that has many buttons, all buttons do the same thing: add 1 every time they are clicked. Every pressed button is sent to a datagridview along with the time they are pressed. Datagrid values look like this:
a_1_serv (button name), 18:05:00(time).
Sometimes I want to delete the last row. Everything works fine so far.
When I delete the last row, I want to change the text of the button (a_1_serv).
I can parse the dgv value (a_1_serv) to a variable but I can't bind it to the appropriate button name so I can control it.
Is there a way to do it?
Don't store your program state in your UI
Create a data structure to hold the information, and let the DataGridView be a "view", not treating it as a variable. You will save yourself headaches vs using the UI as a variable.
That said, create a class to represent your information
Public Class Data
Public Sub New(button As Button, time As DateTime)
Me.Button = button
Me.Time = time
End Sub
<System.ComponentModel.Browsable(False)>
Public Property Button As Button
Public ReadOnly Property Text As String
Get
Return Button.Name
End Get
End Property
Public Property Time As DateTime
End Class
And your code can manipulate the data in a variable off the UI. Bind the data to the DataGridView for display.
Private datas As New List(Of Data)()
Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click, Button3.Click, Button4.Click
addButton(DirectCast(sender, Button))
End Sub
Private Sub RemoveLastButton_Click(sender As Object, e As EventArgs) Handles RemoveLastButton.Click
removeLast()
End Sub
Private Sub addButton(b As Button)
datas.Add(New Data(b, DateTime.Now))
bindData()
End Sub
Private Sub removeLast()
Dim b = datas.Last.Button
b.Text = "new text" ' change to whatever
datas.RemoveAt(datas.Count - 1)
bindData()
End Sub
Private Sub bindData()
DataGridView1.DataSource = Nothing
DataGridView1.DataSource = datas
End Sub
This does exactly what you stated but there may be inconsistency in these two bits of information you provided: a_1_serv (button name) and I want to change the text of the button .... This changes the button text but not the name. The name is displayed in the grid. You can change the data class to display the text or whatever. But the point is this approach will keep your data off the UI and you won't need to look up the control by name anymore.
This is the code when calling form and showing inside panel
Dim frmLubesInterface As LubesInterface = New LubesInterface
with frmLubesInterface
.Text = "frmLubesInterface"
.TopLevel = False
Panel6.Controls.Add(frmLubesInterface)
.StartPosition =
.FormStartPosition.CenterScreen
.Show()
end with
This is code passing data from form and show inside form which is inside of panel
Dim Itemname as string = ""
Itemname = txtItemNameSearch.Text
LubesInterface.txtItem.Text = Itemname - **this part is where i pass the value of data to form textbox inside panel**
To summary i can't pass the value of textbox to form textbox inside the panel, but when showing it as msgbox it show the value.
I am not sure what you mean by "Global" that seems to mean something different to different people.
You could do it in one of two ways as far as I am concerned, you can either pass the values to constructor or create properties and get/set those properties.
Public Class Form1
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Dim TxtFromTxtBoxOnForm2 As String = String.Empty
Dim Form2 As New Form2
With Form2
TxtFromTxtBoxOnForm2 = .ItmTxt
.TopLevel = False
.StartPosition = FormStartPosition.Manual
Panel1.Controls.Add(Form2)
.Show()
End With
End Sub
End Class
Public Class Form2
Public Property ItmTxt As String
Get
Return TextBoxOnForm2.Text
End Get
Set(value As String)
TextBoxOnForm2.Text = value
End Set
End Property
End Class
I already get it. i should declare global and call the form inside the panel.
I have developed one MenuForm one ParentForm and LoadingForm.When MenuForm button click to enter ParentForm If there have heavy process it shows LoadingForm before the process start and closed when process End.
I did everything and working fine except .gif format loading image animation is not working.I don't want to use any image animator class.Now My question is How can i load this .gif format image with animation in picturebox?
Code Snippet has given bellow;
As well as i belief if i get the answer this code snippet helps lot of developer to make simple loading screen using winform rather than using thread and asynchronous way.
' MENU FORM
Public Class frmMenu
Public Property FromForm As Form
Private Sub btnMdr2_Click(sender As Object, e As EventArgs) Handles _
btnMdr2.Click
FromForm = Me
Dim mdr2Form As New ParentForm
mdr2Form.Show()
End Sub
End Class
'PARENT FORM
Public Class ParentForm
Public Property FromForm As Form
Public Sub MachineDailyReportForm_Load(sender As Object, e As EventArgs)_
Handles MyBase.Load
FromForm = Me
'Show loading screen
Dim loadingForm As New LoadingForm(FromForm)
loadingForm.Show()
'Use For loop to delay the process(add data in list) and to see
'loading screen
For i As Long = 0 To 1000000000
If i = 1000000000 Then
Exit For
Else
Continue For
End If
Next
Dim list As New List(Of String)
machineList.Items.Add("Wheel")
machineList.Items.Add("Range")
machineList.Items.Add("Gear")
'Close loading screen
loadingForm.CloseLoadingDialog()
End Sub
End Class
'LOADING FORM
Public Class LoadingForm
Public Property FromForm As Form
Public Sub New(ByVal FromForm As Form)
InitializeComponent()
Me.FromForm = FromForm
End Sub
Public Sub SplashScreen_Load() Handles MyBase.Load
PictureBoxGif.Image = My.Resources.loading
Show()
Refresh()
End Sub
Public Sub CloseLoadingDialog()
Me.Close()
Me.Dispose()
End Sub
End Class
I am using this loading.gif image it display in picture box but without spin.
So far I have looked at several questions and answers for how to get a TextBox within a DataTemplate, but none of it is working for me.
I have xaml like so (minimal example). The data template is in my section for static resources, and the ItemsControl is in the content section:
<DataTemplate x:Key="GridTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140" />
</Grid.ColumnDefinitions>
<sdk:IntegerTextBox DataField="Model.DataField" Width="90" SelectAllOnFocus="True" />
</Grid>
</DataTemplate>
<ItemsControl x:Name="MyControl" ItemsSource="{Binding MyList}" ItemTemplate="{StaticResource GridTemplate}" />
I need to be able set focus to the first IntegerTextBox in the Grid in the code behind. IntegerTextBox inherits the TextBox class.
I first tried writing my own method to recursively search through all UIElements for the first TextBox, but I found that the content within the DataTemplate isn't searchable in this way. The ItemsControl's children always return Nothing:
Private Function FirstTextBox(ByVal uiElement As UIElement) As TextBox
Dim textBox As TextBox = TryCast(uiElement, TextBox)
If textBox IsNot Nothing Then Return textBox
Dim panel As Panel = TryCast(uiElement, Panel)
If panel IsNot Nothing Then
For Each child As UIElement In panel.Children
textBox = FirstTextBox(child)
If textBox IsNot Nothing Then Return textBox
Next
End If
Dim itemsControl As ItemsControl = TryCast(uiElement, ItemsControl)
If itemsControl IsNot Nothing Then
For i As Integer = 0 To itemsControl.Items.Count
textBox = FirstTextBox(CType(itemsControl.ItemContainerGenerator.ContainerFromIndex(i), UIElement))
If textBox IsNot Nothing Then Return textBox
Next
End If
Return textBox
End Function
I have tried this, similar to here and here, but the ContentPresenter is Nothing:
Dim contentPresenter = CType(MyControl.ItemContainerGenerator.ContainerFromIndex(0), ContentPresenter)
Dim textbox As TextBox = CType(CType(contentPresenter.ContentTemplate.LoadContent(), Panel).Children.First(Function(c) TypeOf c Is TextBox), TextBox)
I tried getting the DataTemplate as shown here, then loading the content and searching the children for a TextBox as shown here, but it never finds a TextBox.
I have worked a couple days on this, but I cannot see what I am doing wrong. Is it some obvious mistake, or am I approaching the problem incorrectly? Thanks.
EDIT - This is how I got it to work by adding 100 ms delay:
Private Function FindDescendant(Of TDescendant As DependencyObject)(ByVal obj As DependencyObject) As TDescendant
Dim all = VisualTreeExtensions.GetVisualDescendants(obj)
Dim first = all.OfType(Of TDescendant)().FirstOrDefault()
Return first
End Function
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As ComponentModel.DoWorkEventArgs)
System.Threading.Thread.Sleep(100)
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As ComponentModel.RunWorkerCompletedEventArgs)
Dim firstTextBox = FindDescendant(Of IntegerTextBox)(MyControl)
If firstTextBox IsNot Nothing Then firstTextBox.Focus()
End Sub
Private Sub SetFocus()
Dim bw As New ComponentModel.BackgroundWorker
bw.WorkerReportsProgress = True
bw.WorkerSupportsCancellation = True
AddHandler bw.DoWork, AddressOf bw_DoWork
AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted
bw.RunWorkerAsync()
End Sub
You are approaching the problem incorrectly. Accessing the DataTemplate and searching for a TextBox will get you nowhere.
The template is only a blueprint, only when it is used somewhere (like for each item in your ItemsControl) its content is instantiated (once for each item).
One of several possible solutions to set focus to the first item's textbox:
In your code-behind add an eventhandler to the itemsControl:
MyControl.GotFocus += (sender, args) =>
{
var firstItemTextBox = MyControl.FindDescendant<IntegerTextBox>();
if ( firstItemTextBox != null ) firstItemTextBox.Focus();
};
some helper code:
//you need System.Windows.Controls.Toolkit.dll from the SilverlightToolkit for the class VisualTreeExtensions
using System.Windows.Controls.Primitives;
public static class ControlExtensions
{
public static TDescendant FindDescendant<TDescendant>(this DependencyObject element)
{
return element.GetVisualDescendants().OfType<TDescendant>().FirstOrDefault();
}
}
And btw: why do you wrap the IntergerTextBox in a separate Grid for each item?
I am creating a browser using Cefsharp in VB.Net, and I have been trying to create a download window that shows the progress of the current download. I don't know if I am doing something wrong or if it is the way CEF works, but I put in a download handler by adding browser.DownloadHandler = New DownloadHandler to Form1_Load and creating a new class like this (with downloading being the form I created for showing the progress):
Public Class DownloadHandler
Implements IDownloadHandler
Public Function OnBeforeDownload(downloadItem As DownloadItem, ByRef downloadPath As String, ByRef showDialog As Boolean) As Boolean Implements IDownloadHandler.OnBeforeDownload
downloadPath = downloadItem.SuggestedFileName
showDialog = True
downloading.Show()
Return True
End Function
Public Function OnDownloadUpdated1(downloadItem As DownloadItem) As Boolean Implements IDownloadHandler.OnDownloadUpdated
My.Settings.downloadpercent = downloadItem.PercentComplete.ToString
Return False
End Function
End Class
On the downloading form I have this code for showing the progress:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim percentcomplete As Integer = My.Settings.downloadpercent * 5
Me.PictureBox1.Size = New Size(percentcomplete, 25)
End Sub
Private Sub downloading_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Timer1.Start()
End Sub
This may not be the best way to show a ProgressBar, but I have a picture box that just has a green bar, and the total width of the form is 500px. The code is telling it to read the PercentComplete setting put in My.Settings.downloadpercent, multiply it by 5, so when the progress in 100%, it will go across the whole form.
The problem is that the ProgressBar is not being updated to show the current progress. It goes a little bit, but then it just stops. Am I doing something wrong, or is OnDownloadUpdated not a good place to put that? Any suggestions of how to fix this?
Edit:
I am using CefSharp 39.0.0-pre03. Also, when the save file dialog comes up, no matter if you click Save or Cancel, the browser always triggers a LoadError, so it loads the custom HTML error page I made, and since it requires a URL for loading HTML, I put in "http://rendering/"... So I guess that would be a domain change. That issue (in the comments) could be the problem, but then we also need to figure out why it is triggering a LoadError.
A simple solution that may be of interest to those who faced the same or similar problem:
Declare Public your Picturebox, in a module:
Module Module1
Public PictureBox1 As New PictureBox
End Module
In MainForm you can declare the attributes you want (after the InitializeComponent). Example:
With PictureBox1
.BorderStyle = Border3DStyle.Flat
.Image = Bitmap.FromFile(YourImageFileName)
'......
End With
In the DownloadHandler Class:
Public Function OnDownloadUpdated1(downloadItem As DownloadItem) As Boolean
Implements IDownloadHandler.OnDownloadUpdated
Dim percentcomplete As Integer=downloadItem.PercentComplete * 5
PictureBox1.Size = New Size(percentcomplete, 25)
Return False
End Function