I have a WPF application. In one of the XAML I have used Name attribute like as follows
x:Name="switchcontrol"
I have to access the control/property in .cs file using this.switchcontrol
My question is, I need to access the control in static method like
public static getControl()
{
var control = this.switchcontrol;//some thing like that
}
How to achieve this?
this is not accessible in static method. You can try save reference to your instance in static property, for example:
public class MyWindow : Window
{
public static MyWindow Instance { get; private set;}
public MyWindow()
{
InitializeComponent();
// save value
Instance = this;
}
public static getControl()
{
// use value
if (Instance != null)
var control = Instance.switchcontrol;
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
Instance = null; // remove reference, so GC could collect it, but you need to be sure there is only one instance!!
}
}
Some alternatives to Tony's method - you could pass in the window (or whatever xaml construct you are using) as a reference to the method, e.g.
public static void GetControl(MainWindow window)
{
var Control = window.switchcontrol;
}
if you are going to be passing several different derived types of Window, you could also do this:
public static void GetControl(Window window)
{
dynamic SomeTypeOfWindow = window;
try
{
var Control = SomeTypeOfWindow.switchcontrol;
}
catch (RuntimeBinderException)
{
// Control Not Found
}
}
Related
I made a class which requires the public default constructor but
that is never called; instead another constructor is used at DataGrid.AddingNewItem.
I'd like to tell developers that the default constructor is not for their use.
Is there an attribute which suits the purpose?
I had checked DebuggerNonUserCode and MethodImplAttribute with MethodImplAttributes.InternalCall but not sure that's the proper approach.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.dataGrid1.CanUserAddRows = true;
var list = new List<RowX>();
this.dataGrid1.ItemsSource = CollectionViewSource.GetDefaultView(list);
this.dataGrid1.AddingNewItem += (s, e) => e.NewItem = new RowX("ABC");
}
}
public class RowX
{
public RowX()
{
//this is not used. but CollectionView require this to be public or
//CanUserAddRows doesn't work.
}
public RowX(object o)
{
//this is the actual ctor.
}
public string Text { get; set; }
}
Mark it private
class Foo
{
private Foo() {}
}
You can give your constructor an access modifier.
private This means it can only be called from another constructor in that class.
public class PrivateClass
{
//Only from inside this class:
private PrivateClass()
{
}
public static PrivateClass GetPrivateClass()
{
//This calls the private constructor so you can control exactly what happens
return new PrivateClass();
}
}
internal This means only code in the same assembly (i.e. from inside your library) can access it.
public class InternalClass
{
//Only from within the same assembly
internal InternalClass(string foo)
{
}
}
I have a form (MainPage) and I set a UserControl in it some times, So I write a method in that form like this to invoke:
delegate void containerPanelCallback(UIPart uiPart);
public void IncludeUIPart(UIPart uiPart)
{
if (this.containerPanel.InvokeRequired)
{
containerPanelCallback d = new containerPanelCallback(IncludeUIPart);
containerPanel.Invoke(d, new object[] { uiPart });
}
else
{
containerPanel.Controls.Clear();
containerPanel.Controls.Add(uiPart);
}
uiPart.Size = this.containerPanel.Size;
uiPart.Dock = DockStyle.Fill;
}
UIPart class inherit from UserControl that my UserControls inherit from UIPart.
This method and invoke launched like this:
public class myClass
{
...
private static MainPage _frmMain;
private static myUIPart6 UIP6;
...
public static void aMethod(/* Some arguments */)
{
UIP6 = new myUIPart6 { /* Some settings of properties */ };
_frmMain.IncludeUIPart(UIP6);
_frmMain.Show(); /*Throws an error*/
}
...
}
The error is:
Cross-thread operation not valid: Control 'MainPage' accessed from a thread other than the thread it was created on.
I found many questions and many answers here about this error, But I can't figure it out why it is throwing at _frmMain.Show();?, Should I invoke something else? Or Am I in a wrong way? Is it related to creation of Handle of my UserControl?
Try adding the following code:
public static void aMethodCaller(){
if (_frmMain.InvokeRequired)
_frmMain.Invoke(new Action(aMethod));
else
aMethod();
}
and replace all references to aMethod() in your code to aMethodCaller()
Below is the sample code:
class Foo
{
static Form _frmMain;
public static void aMethod()
{
_frmMain.Show();
}
public static void aMethodCaller()
{
if (_frmMain.InvokeRequired)
_frmMain.Invoke(new Action(aMethod));
else
aMethod();
}
}
The _frmMain.Show() isn't guarded by any invocation requirement check. So you're probably calling it in a background thread.
Using VS 2013, C#, Windows Store App
I need to send one object from main Frame to new one and then work with it.
So i have main Frame, second Frame (for work with sended object) and DataModel.
Idea - is to display all data that i have at main frame, than choose one object, press on it, after pressing new Frame will appear and you can work with selected items in new frame.
Problem - how to send object from one Frame to another.
Currently i made next: create additional static class that with static property:
public static class GetCurrentEvent
{
public static Event CurrentEvent { get; set; }
}
So, at first i call to property of this class at main Frame, and save required object using it:
private void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
var clickedItems = (Event)e.ClickedItem;
GetCurrentEvent.CurrentEvent = new Event(
clickedItems.UniqueId,
clickedItems.Name,
clickedItems.Place,
clickedItems.Description,
clickedItems.Start,
clickedItems.End,
clickedItems.ImagePath
);
if (this.Frame != null)
{
this.Frame.Navigate(typeof(ChangeEvent));
}
}
After that i use this property in new Frame:
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
this.DataContext = GetCurrentEvent.CurrentEvent;
...
}
All works, but i think that it's not the perfect method.
So,the quesion how i can change code abowe for improving methods, or how i can send object from one class to another?
EDIT
Choosed varinat to send object from Frame to Frame - use Parameter:
var clickedItems = (Event)e.ClickedItem;
this.Frame.Navigate(typeof(ChangeEvent), clickedItems);
and then convert to required type in new Frame:
this.DataContext = (Event)e.NavigationParameter;
There are many many ways that this accomplished and this tends be an opinionated debate.
I typically opt for a simple solution, such as saving a state/session variable in a global accessible singleton. I call the singleton Global and keep it in the root of the namespace.
Example:
public sealed class Global
{
#region Singlton Contructor
Global() { }
static readonly Global instance = new Global();
public static Global Default
{
get { return instance; }
}
#endregion
#region Global Settings
public Settings Settings {get;set;}
private AuthenticatedUser _authenticatedUser;
public AuthenticatedUser AuthenticatedUser
{
get
{
return _authenticatedUser;
}
set { _authenticatedUser = value; }
}
private UserSession _currentSession;
public UserSession CurrentSession
{
get
{
if (_currentSession == null) _currentSession = UserSessionService.UserSessionFactoy();
return _currentSession;
}
private set { _currentSession = value; }
}
#endregion
}
CurrentSession in this case keeps track of the objects I want to pass frame to frame. And its easily accessed by using
Global.CurrentSession.SomePropertyOrObject
I have one static method which I call from another class when I need update data in listbox. But then I need scroll listbox to last item. Here is code:
public static void updateMessages()
{
MyDatasCurentUser.Clear();//clear messages from previewous user from datas
foreach (var items in UniDB.returnlistOfMessagesData(IdOfChoosenUser, MainContentPage.myID))
{
_mydataCurentUser.Add(new BindingData
{
MessengerReadTime = new DateTime(items.readTime.Year, items.readTime.Month, items.readTime.Day, items.readTime.Hour, items.readTime.Minute, 0),
MessengeFullName = items.senderName,
MessengerTime = new DateTime(items.sendTime.Year, items.sendTime.Month, items.sendTime.Day, items.sendTime.Hour, items.sendTime.Minute, 0).ToString("dd.MM.yyyy - HH:mm"),
MessengerMessage = items.message,
MessengerIsFromMe = items.isFromMe,
});
}
lbChoosenMessagesUsers.ScrollIntoView(lbChoosenMessagesUsers.Items.Last());
}
But I get error cannot access to non static field in static context at this: lbChoosenMessagesUsers.ScrollIntoView(lbChoosenMessagesUsers.Items.Last());
Is there any way how I can do this lbChoosenMessagesUsers.ScrollIntoView(lbChoosenMessagesUsers.Items.Last()); when is method updateMessages() called?
If you have a non static method of one class:
class Form1
{
public void UpdateMessages()
{
// ...
lbChoosenMessagesUsers.ScrollIntoView(lbChoosenMessagesUsers.Items.Last());
}
}
And you want to call it from an object of a different class, that object will need a reference to the first object. A common solution is to pass the reference to the first object into the constructor of the second:
class OtherClass
{
Form1 _form;
OtherClass(Form1 form)
{
_form = form;
}
void Method()
{
//can access the methods of the other object
_form.UpdateMessages();
}
}
Alternatively you could pass the object in later:
class OtherClass
{
public void Method(Form1 form)
{
form.UpdateMessages();
}
}
I've searched Google all day and can't find the correct answer to my issue, hoping someone here can help me.
So, in the "Main" form I have the method to show a form that needs to be centered directly above the parent form (frmMain). Normally I would call ShowDialog(this) to see the parent, but for some reason I have to set the loadNewsFeedItem to static in order to see the method from the flpNewsFeedHeader : Label derrived class (below). The OnClick event triggers the method loadNewsFeedItem().
When I call this to set the parent, I'm getting the message "Keyword 'this' is not valid in a static property, static method, or static field initializer"
namespace NewsFeeds
{
public partial class FrmMain : Form
{
public static void loadNewsFeedItem()
{
frmNewsFeedView frmFeedView = new frmNewsFeedView(FrmFuncs.selFeedID);
frmFeedView.ShowDialog(this); // Error occurs on this line, when calling this via a static method
}
}
}
public class flpNewsFeedHeader : Label
{
private int FeedID = 0;
public int theFeedID
{
get { return FeedID; }
set { FeedID = value; }
}
protected override void OnClick(EventArgs e)
{
FrmFuncs.selFeedID = FeedID;
Thread thrShowFeed = new Thread(new ThreadStart(FrmMain.loadNewsFeedItem));
thrShowFeed.Start();
}
}
Can someone please give me a corrected code example or a hint as to how to get the loadNewsFeedItem() to be visible without setting the accessor to static, or how to work around this in a static accessor?
Thanks in advance!
Chris
Edit: used ActiveForm for owner.
public partial class FrmMain : Form
{
public static void loadNewsFeedItem(Form owner)
{
frmNewsFeedView frmFeedView = new frmNewsFeedView(FrmFuncs.selFeedID);
frmFeedView.ShowDialog(owner);
}
}
}
public class flpNewsFeedHeader : Label
{
private int FeedID = 0;
public int theFeedID
{
get { return FeedID; }
set { FeedID = value; }
}
protected override void OnClick(EventArgs e)
{
FrmFuncs.selFeedID = FeedID;
// Shouldn't need a new thread. Already on the GUI thread.
FrmMain.loadNewsFeedItem (System.Windows.Forms.Form.ActiveForm);
}
}
may be you mean this:
frmFeedView.Owner = System.Windows.Forms.Form.ActiveForm;
frmFeedView.ShowDialog();
In a static method, this is meaningless. One option is to skip the parameter
frmFeedView.ShowDialog();
The other option is to setup a static variable as shown below (but beware, it can have side effects if you try to open multiple instances of FrmMain)
public partial class FrmMain : Form
{
private static FrmMain staticInstance;
public FrmMain()
{
staticInstance = this;
InitializeComponent();
...
}
public static void loadNewsFeedItem()
{
frmNewsFeedView frmFeedView = new frmNewsFeedView(FrmFuncs.selFeedID);
frmFeedView.ShowDialog(staticInstance );
}