How do I pass a value from one a variable to a textbox after it's set? On winforms, I used to use form1.textbox1.text = variable in winforms.
I set, and get the variable from this...
Public Shared Property containerstring() As String
Get
Return m_containerstring
End Get
Set(value As String)
m_containerstring = value
End Set
End Property
Private Shared m_containerstring As String
Basically, I have a window... where the user chooses a variable, this variable is then set # containerstring. When this form closes, I wanted to push this variable to the currently open window's textbox.
I'm new to WPF, forgive the noobness.
This is how I do it for a window, and this works perfectly... for windows. I'm looking to do the same thing with a control.
Dim strWindowToLookFor As String = GetType(MainWindow).Name
Dim win = ( _
From w In Application.Current.Windows _
Where DirectCast(w, Window).GetType.Name = strWindowToLookFor _
Select w _
).FirstOrDefault
If win IsNot Nothing Then
DirectCast(win, MainWindow).Title = SelectedContainer
End If
You can make a Window closing Event like :
this.Closed += MyWindow_Closed;
and then set your variable in the corresponding method.
private void MyWindow_Closed()
{
TextBox1.Text = a;
}
You could use a PubSubEvent which is available in Prism.Events. This will allow you to subscribe to events.
Using Prism.Events;
define your Event.
public class MyEvents : PubSubEvent<object>
{
public MyEvents();
}
In your first window or code behind
[Import]
public IEventAggregator EventAggregator
{
get;
set;
}
and you can use this property in your program to send whatever value you want to send.
For example
private void MyWindow_Closed()
{
MyEvents myEvents = EventAggregator.GetEvent<MyEvents>();
myEvents.Publish(yourvalue);
}
Once you have publised you can Subscribe to the same event in any other part of your program like this.
MyEvents myEvents = EventAggregator.GetEvent<MyEvents>();
myEvents.Subscribe(MyEventMethod, ThreadOption.UIThread, true);
and get your data here
void MyEventMethod(object obj)
{
// do wharever you want
}
Related
I used next code
private String _Value = "hello";
//Set - just copy from value in _Value with PropertyChanged?.Invoke.
public String Value {get => _Value; set => Set(ref _Value, value);}
public ICommand DoSomeCommand{get => new SomeCommand(value);}
SomeCommand - the class that creates the command object, and saving value data.
get=>new SomeCommand(vale);
Initialize only ones at start of program, and keeps the value as "hello", even if i changed Value.
So i need to create new instance anytime my program calls the given command. As I understand it, all commands are stored in a buffer. But is it possible to have the command create a new instance with a new value when accessed?
For example, when i click on some button(which has this command) any time, new instance DoSomeCommand created and command with new value executed.
Bindings are automatically updated only when the view is initialized or when the source property changes.
So if you want to keep your command implemented this way, you have to manually notify PropertyChanged event for your command when your Value property changes.
Possible implementation (assuming your Set() method returns true if the value changed):
private String _Value = "hello";
public String Value
{
get => _Value;
set =>
{
if (Set(ref _Value, value))
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DoSomeCommand)));
}
}
}
public ICommand DoSomeCommand
{
get => new SomeCommand(value);
}
I understand that List, Array, Object etc. types "copied" by reference. However my natural and ordinary intend is to just have a "copy" of it in this context where I intentionally use ReadOnly instead of Read/Write property. In below sample the ReadOnly 'Extensions' property get change through 'm_extensions' reference change. Regardless, I think this behavior is incorrect and I have to do extra work to prevent ReadOnly properties from being overwritten. Is there any built in keyword to use for 'm_extensions' value protection?
Public Classs A
' more properties and methods here...
Private m_extensions() As String = {"*.abc", "*.def"}
Public ReadOnly Property Extensions() As String()
Get
Return m_extensions
End Get
End Property
End Class
Public Classs B
' more stuff here...
Private Function BuildFilter() As String
Dim l() As String = A.Extensions
Dim s As String = String.Empty
For m As Integer = 0 To l.Length - 1
Select Case l(m).ToLower
Case "*.*" : s = "All Files"
Case "*.abc" : s = "ABC File"
Case "*.def" : s = "DEF File"
Case Else : s = "XYZ File " + m.ToString
End Select
l(m) = String.Format("{1} ({0})|{0}", l(m), s)
Next
Return String.Join("|", l)
End Function
End Class
Readonly modifier means that anything using the property cannot change the reference that you protected this way (e.g. cannot set it to Nothing). It doesn't prevent changing the values in the array returned from that property.
One way around it could be to copy the array inside the property. This will prevent modifications of the original array:
Public ReadOnly Property Extensions() As String()
Get
Return m_extensions.Clone()
End Get
End Property
I have the following custom datagrid column, for passing in the value of the DatePart dependency property as the ConverterParameter to the editing element's converter:
Public Class DataGridTimeColumn
Inherits DataGridTextColumn
Shared ReadOnly DatePartProperty = DependencyProperty.Register("DatePart", GetType(DateTime?), GetType(DataGridTimeColumn), New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, AddressOf RefreshBinding))
Property DatePart As DateTime?
Get
Return GetValue(DatePartProperty)
End Get
Set(value As DateTime?)
SetValue(DatePartProperty, value)
End Set
End Property
Private Shared Sub RefreshBinding(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
Dim tc As DataGridTimeColumn = d
tc.Binding = tc.Binding
End Sub
Public Overrides Property Binding As BindingBase
Get
Return MyBase.Binding
End Get
Set(value As BindingBase)
Dim b As Data.Binding = value
With b
.Converter = New TimeConverter
.ConverterParameter = DatePart
End With
MyBase.Binding = b
End Set
End Property
End Class
With the following XAML:
<my:DataGridTimeColumn Header="From" Binding="{Binding FromDate}" DatePart="{Binding FromDate}" />
<my:DataGridTimeColumn Header="Until" Binding="{Binding TillDate}" DatePart="{Binding TillDate}" />
But RefreshBinding is never called (I've set a breakpoint and it's never triggered), and thus DatePart is always Nothing(null) when the ConverterParameter is set. How can I fix this?
Edit
In C#:
public class DataGridTimeColumn : DataGridTextColumn
{
static readonly DependencyProperty DatePartProperty = DependencyProperty.Register(
"DatePart", typeof(DateTime?), typeof(DataGridTimeColumn),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, RefreshBinding)
);
public DateTime? DatePart
{
get { return (DateTime?)GetValue(DatePartProperty); }
set { SetValue(DatePartProperty, value); }
}
private static void RefreshBinding(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var tc = (DataGridTimeColumn)d;
tc.Binding = tc.Binding;
}
public override System.Windows.Data.BindingBase Binding
{
get { return base.Binding; }
set
{
var b = (Binding)value;
b.Converter = new TimeConverter();
b.ConverterParameter = DatePart;
base.Binding = b;
}
}
}
I might not understand what you're exactly trying to do, but this seems like a lot of work to just view/edit the DatePart. Would using a formatter and a DataGridTextColumn be easier? WPF Binding StringFormat Short Date String
First, please use debug to check your binding path whether it is ok.
Second, check your FromDate property whether is triggered.
Third, please use Snoop to monitor this DP whether is updated.
Last, i remember DataGrid has dynamic binding bug, so i am not sure above steps can solve your problem. If it is not ok , please let me know.
I would recommend Darlene approach if you only need to format the value. If you really need a converter for some magic I would recommend to set it via your binding in the XAML (I don't really know why you are trying to set it in the property definition).
Your XAML will be something like this:
<my:DataGridTimeColumn Header="From" Binding="{Binding FromDate, Converter={StaticResource myTimeConverter}} />
TimeConverter must implement IValueConverter and an instance must be defined in your window/datagrid resources. You can also define the TwoWay in that binding.
You can find a full example here.
In case you want to combine two or more pieces of data you can use a MultiBinding.
Tried to understand what you want to achieve from the comments and if I got it right you can do it using only the view model and a converter with a small workaround:
In your converter ConvertBack method, you can try to figure out if the value entered by the user has only the time part and if so set the date to something that will not be used (for example DateTime.MinValue):
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var convertedDateTime = DateTime.Parse(value.ToString());
var hasOnlyTime = value.ToString().Trim().Length <= 5; // This should be replaced with something more consistent
if (hasOnlyTime)
return new DateTime(DateTime.MinValue.Year, DateTime.MinValue.Month, DateTime.MinValue.Day, convertedDateTime.Hour, convertedDateTime.Minute, convertedDateTime.Second);
return convertedDateTime;
}
Then in the object setter for the date you can check that and use the required value, if the date part is DateTime.MinValue change it back to the previous one, if not leave it as it is:
private DateTime _fromDate;
public DateTime FromDate
{
get { return _fromDate; }
set
{
if (value.Date != DateTime.MinValue)
_fromDate = value;
else
_fromDate = new DateTime(_fromDate.Year, _fromDate.Month, _fromDate.Day, value.Hour, value.Minute, value.Second);
OnPropertyChanged("FromDate");
}
}
Tested on .NET 4.5 and works as expected.
I have a parameterised constructor in My Application. I want to add controls dynamically to my silverlight Child Control Page. But it gives NullReferenceException.
I can't find out why it returns null.Can any help me with this situation?
public PDFExport(FrameworkElement graphTile1, FrameworkElement graphTile2,FrameworkElement graphTile3)
{
Button btnGraph1 = new Button();
string Name = graphTile1.Name;
btnGraph1.Content = Name;
btnGraph1.Width = Name.Length;
btnGraph1.Height = 25;
btnGraph1.Click += new RoutedEventHandler(btnGraph1_Click);
objStack.Children.Add(btnGraph1);
LayoutRoot.Children.Add(objStack); // Here am getting null Reference Exception
_graphTile1 = graphTile1;
_graphTile2 = graphTile2;
_graphTile3 = graphTile3;
}
Thanks.
I guess objStack is a stackpanel declared in your XAML?
Be aware that the UI component of your xaml are build by the call to InitializeComponent.
Thus objStack will not exist until you call InitializeCOmponent() in your constructor.
Also, you should know that the call to InitializeComponent is asynchronous, so you code should look like something like that:
private readonly FrameworkElement _graphTile1;
private readonly FrameworkElement _graphTile2;
private readonly FrameworkElement _graphTile3;
public PDFExport(FrameworkElement graphTile1, FrameworkElement graphTile2, FrameworkElement graphTile3)
{
_graphTile1 = graphTile1;
_graphTile2 = graphTile2;
_graphTile3 = graphTile3;
}
private void PDFExport_OnLoaded(object sender, RoutedEventArgs e)
{
Button btnGraph1 = new Button();
string Name = _graphTile1.Name;
btnGraph1.Content = Name;
btnGraph1.Width = Name.Length;
btnGraph1.Height = 25;
btnGraph1.Click += new RoutedEventHandler(btnGraph1_Click);
objStack.Children.Add(btnGraph1);
LayoutRoot.Children.Add(objStack);
}
Hope it helps.
As per my research i got that, why it raises an exception: Because there is no
InitializeComponent() in My Constructor and am not calling parent constructor.
That is the reason it raises Exception.
Just Add InitializeComponent() to the code, simple
I've been using WinForms databinding to display data from a database mapped with Fluent NHibernate, and that's been working great.
For example, I can just set a DataGridView's DataSource property from an entity's IList property, and voila - there's all the data!
But now I need to start adding and saving new data rows, and that's not going so well. I thought I'd be able to just enable the grid's AllowUserToAddRows property, and new rows would get added to the underlying IList in the entity, but that didn't work.
Then, after a little searching, I tried setting the DataSource property to a BindingList that was populated from the IList, but that's not being updated with new rows either.
During the course of my searches, I also came upon a few people reporting difficulty with WinForms and DataBinding in general, which makes me wonder if I should pursue that approach any further.
Is the DataBinding approach worth continuing? If so, can anyone suggest where I'm going wrong?
Or is it better to just handle all the DataGridView events associated with adding a new row, and writing my own code to add new objects to the IList property in my entity?
Other suggestions? (though I don't think switching to WPF is going to be an option, no matter how much better the databinding may be)
Can you load (or copy) your nHibernate entities into a generic List? If so, I have had good success in with two-way binding using a DataGridView bound to a generic List.
The key points are:
The generic list contains list objects where each is an instance of your custom class.
Your custom class must implement public properties for each of the fields to bind. Public fields didn't work for me.
Use a BindingSource to wrap the actual generic list.
The BindingSOurce allows you to set the AllowNew property to true. Binding directly to the List almost works, but the DataGridVieww does not display the "New row" line, even if AllowUsersToAddRows = true.
For example, add this code to a Form with a dataGridView1:
private List<MyObject> m_data = new List<MyObject>();
private BindingSource m_bs =new BindingSource();
private void Form1_Load(object sender, EventArgs e)
{
m_data.Add(new MyObject(0,"One",DateTime.Now));
m_data.Add(new MyObject(1, "Two", DateTime.Now));
m_data.Add(new MyObject(2, "Three", DateTime.Now));
m_bs.DataSource = m_data;
m_bs.AllowNew = true;
dataGridView1.DataSource = m_bs;
dataGridView1.AutoGenerateColumns = true;
dataGridView1.AllowUserToAddRows = true;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
for (int i = 0; i < m_data.Count ; i++)
{
Console.WriteLine(string.Format("{0} {1} {2}", m_data[i].ID, m_data[i].Name, m_data[i].DOB));
}
}
}
public class MyObject
{
// Default ctor, required for adding new rows in DataGridView
public MyObject()
{
}
public MyObject(int id, string name, DateTime dob)
{
ID = id;
Name = name;
DOB = dob;
}
private int m_id;
public int ID
{
get
{
return m_id;
}
set
{
m_id = value;
}
}
private string m_name;
public string Name
{
get
{
return m_name;
}
set
{
m_name = value;
}
}
private DateTime m_dob;
public DateTime DOB
{
get
{
return m_dob;
}
set
{
m_dob = value;
}
}
}
When the form closes, the contents of the bound List are printed to the Output window.