如何从窗口单击事件访问页面中的方法 [英] How to access a method in a page from a Window click event

查看:118
本文介绍了如何从窗口单击事件访问页面中的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的WPF项目中有一个父窗口.父窗口具有选项卡式界面. TabItems是在窗口中单击不同的菜单选项时打开的不同页面.现在,我在窗口中有一些按钮,我的动机是在主窗口中创建一个通用控件,例如打印或删除.当我单击此按钮时,它将在当前打开的选项卡式子页面上生效.假设我有两个子页面:-
1>物品大师
2>帐户管理员
这两个页面均在父窗口的选项卡式界面中打开,当前正在查看/选择/激活tabItem的项目母版"页面.
现在我在主窗口的通用控件面板中有了删除选项.
当我从项目母版中的网格中选择任何项目,然后在主窗口中单击删除按钮时,它将直接从该项目母版页中删除该项目.

现在,我要选择帐户主数据"选项卡及其活动标签,以便从帐户主数据"页面网格中打印记录.我从其页面上的帐户主网格中选择一条记录,然后单击主窗口上的打印"按钮.来自该帐户主数据的记录将被打印.
我不希望使用非常复杂的工具或四舍五入的方式来将print和delete方法写入页面本身.所有页面都将具有此方法,并且仅以该方法编写执行操作的代码.我需要的是在单击窗口通用控件按钮的页面上触发此方法.如果我有一种方法可以根据页面要求从页面本身禁用此按钮也很好,例如某些页面可能没有任何此类数据可打印,因此在该页面处于活动Tabitem时将禁用窗口中的按钮.

所以这是我没有的总体情况.菜单驱动页面的集合均作为选项卡项目打开.我想要做的是,当我从主窗口的通用控件中单击一个按钮时,它会触发当前活动的Tabitem页面的事件.

我怎样才能做到这一点,请帮帮我,我是wpf的新手.举例说明会有所帮助.

谢谢你

I have a Parent Window in my WPF project. The parent window has a tabbed interface. The TabItems are the different Pages that open on clicking different Menu options in the Window. Now I have some buttons in the Window, my motive is to create a common control like print or delete in the main window. When I click this buttons it will take its effect on the currently opened tabbed child page. Suppose I have two Child pages :-
1>Item Master
2>Account Master
both of these pages are opened in tabbed interface of the parent window, the Item Master page is currently being viewed/selected/active tabItem.
now I have the delete option from common controls panel in the Main window.
When I select any Item from a grid in the Item master and click delete button in Main window it will delete the Item from that Item Master page directly.

Now I select The Account Master Tabitem and its the active tabitem I want to print a record from the account Master page grid. I select a record from account master grid in its page and click the print button on the main window. That record from that account master gets printed.
I don''t want a very complicated tool or round about way cause the print and delete methods are written in the page itself. All pages would have this methods and codes to perform the actions will be written in that method only. All i need is to fire this methods in the page on the click of window common control buttons. It would also be good if i get a way to disable this buttons from the page itself according to page requirement e.g. some page might not have any such data to print so that button from the window will be disabled while the page is active tabitem.

So this is total scenario I have no. of menu driven pages all opens as tab item. What I want to do is when I click a button from the common control of the main window it fires the event of the currently active tabitem page.

how can I achieve this, please help me out I am new to wpf. Explanation with some examples would be helpful.

Thank You

推荐答案

Sinha先生写道:
Mr J Sinha wrote:


private void MenuItem_Click_AcMap(object sender, RoutedEventArgs e)
{
    if (TabWindow.Items.Contains(tabAcMap) == false)
    {
        Frame tabFrame = new Frame();
        tabAcMap.Title = "AC Mapping Master";
        tabAcMap.IsEnabled = true;
        MstAccMapping DepCls = new MstAccMapping();
        tabFrame.Content = DepCls;
        tabAcMap.FontSize = 9;
        tabAcMap.Content = tabFrame;
        TabWindow.Items.Add(tabAcMap);
        TabWindow.SelectedItem = tabAcMap;
    }
    else
    {
        TabWindow.SelectedItem = tabAcMap;
    }
}



这就是我动态创建选项卡项目并在主窗口的该选项卡项目中设置我的页面的方式.我说我是新手...但是放弃并不是我的选择,所以在...在这种情况下,如何通过单击窗口按钮来访问此页面中的事件...我找不到可以动态找到Tabitem及其内容的任何可能方式



This is how i dynamically create the tab item and set a my page in that tab item in the main window.. I said I''m new to it... but giving up is not and option for me... so in this case how do i get to access the events in this page from the window button click... i cant find any possible way in which i can dynamically find the tabitem and its contents inside it

不放弃?我的尊敬.

让我们来看看.首先,下一次,不要在不可读的地方添加代码.我已经建议使用改进问题",在这里您可以正确地设置代码格式(见上文).

什么是访问事件"?正如我所解释的,对于您未在类中声明的事件,您只能处理它们.您需要了解其含义和含义.基本上,您将创建一些具有必需签名的委托实例(成为事件处理程序),然后使用运算符"+ ="将其添加到事件实例的调用列表中.然后,每次调用事件时,都会调用添加的委托实例的方法.您可以将多个句柄添加到同一个委托实例.如我在文章动态方法分派器"中第4.1节所述,它们将作为委托实例添加: ^ ].

当某些事件调用事件时,将调用您所有的事件处理程序.您可以添加更多,甚至删除一些.如果它是您自己的类中的常规"委托实例,则可以控制此实例,但是您所拥有的也会调用所有处理程序.

现在,您需要在没有设计人员帮助的情况下自己添加处理程序(实际上,我几乎从来不允许设计人员为我添加事件句柄,但这可以视个人喜好而定).例如,看起来您的tabAcMapTabItem类型.让我们来看看如何添加一个事件处理程序,以便在每次该项目获得焦点时被调用:

Not giving up? My respect.

Let''s see. First of all, next time, don''t put code in comment, where it is unreadable.I already suggested to use "Improve question", where you can format code properly (see above).

What is "access events"? As I explained, for the events you did not declare in your class, you can only handle them. You need to understand how and what it means. Basically, you create some delegate instance (to become an event handler), of required signature and add it to the invocation list of the event instance using the operator ''+=''. Then the method of the delegate instance added will be called every time the event is invoked. You can added several handles to the same delegate instance; they will be added as for delegate instances, as I explained in my article "Dynamic Method Dispatcher", in the section 4.1: Dynamic Method Dispatcher[^].

When something invokes the event, all you event handlers are called. You can add more or even remove some. If it was "regular" delegate instance in your own class, you could control this, but what you have will also call all handlers.

Now, you need to add a handler yourself, without the help of the designer (I actually nearly never allow the designer to add event handles for me, but this can be considered as a matter of individual taste). For example, it looks like your tabAcMap is of the type TabItem. Let''s see how to add an event handler to be called each time this item gets focus:

tabAcMap.GotFocus += (sender, eventArgs) => {
    // let's illustrate how to find the instance of TabItem inside the handler:
    TabItem senderAsTypeItem = (TabItem)sender;
    // eventArgs are insignificant here,
    // but in many other events that carry data,
    // for example, mouse coordinates
    // and, now:
    DoSomethingInResponseToGettingFocus(senderAsTypeItem);
};

这种lambda表示法的方便之处在于它为参数包括了类型推断,因此您不必编写sendereventArgs的类型,但是您可以随时在文档中阅读每个事件的委托类型,它们是什么.通常,人们只是看智能感知所显示的内容.还有其他形式:

The convenience of this lambda notation is that it includes type inference for the arguments, so you don''t have to write the types of sender and eventArgs, but you can always read in the documentation on each event''s delegate type what are they. More usually, people just look what intellisense shows. There are other forms:

tabAcMap.GotFocus += MyMethodHandlingGotFocus; // no new required as many mistakenly think
// but you need to have some method MyMethodHandlingGotFocus with precisely correct signature
// (two parameters mentioned above)


另一种匿名形式,等效于第一个示例:


Another anonymous form, equivalent to the first sample:

tabAcMap.GotFocus += delegate(/* with exact parameter type */) {/* ... */}



在这两种匿名形式中,您都可以访问"this"(对声明类的实例的引用),这就是例如可以调用其实例方法(例如"DoSomethingInResponseToGettingFocus")的原因.而且,自然地,如果处理程序方法(第二个示例)是实例方法,则具有相同的结果.使用这两种匿名方法形式,您还可以使用关闭的效果: ^ ].
但是请注意关闭;如果您不太了解它是如何工作的,请通过"this"传递处理所需的所有对象.

您没有解释哪个事件(您是全部意思吗?这不是事情的工作原理),所以我只显示了一个.如果需要使用EventArgs成员,希望您能应付.有什么不清楚的地方吗?询问其他问题.

—SA



In both anonymous forms, you have access to "this", the reference to the instance of declaring class, that''s why you can, for example, call its instance methods (such as "DoSomethingInResponseToGettingFocus"). And, naturally, you have the same if you handler method (2nd sample) is the instance method. With both anonymous method forms, you can also use the effect of closure: http://en.wikipedia.org/wiki/Closure_(computer_programming)[^].
But be careful with closures; if you poorly understand how it works, pass all objects needed for handling through "this".

You did not explain which events (did you mean all? this would be not how things work), so I''ve shown only one. Hope you can cope with EventArgs members if there is a need to use them. Something unclear? Ask further questions.

—SA


问题很清楚,我很欣赏,但是必须要复杂得多.这种方法是错误的.您应该抓住真正问题的本质,并尝试将您的应用程序简化为尽可能简单的问题.问问自己:在哪种最简单的应用程序中,我会遇到相同的问题",然后用全面的代码示例对其进行更好地描述.

但这只是时间.我清楚地了解了这个问题(或其可理解的部分).基本上,您缺少两件重要的事情.

第一件事是:没有诸如页面上的方法"之类的东西. TabPage只是控件之一,它是某些类的成员,这些类可以是您的窗口类,您自定义的类或用户控件类,或者其他类.与该页面特别相关的方法可以是此类的方法,即静态方法,该方法可以通过其参数接受对任何控制实例的引用.或者它可以是此类的实例方法,这意味着它可以具有相同或其他参数,外加一个额外的方法,即隐式方法"this",您可以在此方法的主体内部访问该类的实例. .就这样.这是关键:您需要了解问题在某种程度上是人为的:1)方法的范围是类,该实例是许多控制实例的父级(直接+间接); 3)控件实例引用可以作为参数传递给它.

您还有另一件事想念吗?您是否注意到在问题的标题中您正在询问方法,最后您正在询问触发事件"?那是完全不同的东西.您不能真正触发"事件(正确的术语是调用事件").更确切地说,您只能在声明此事件的类型的方法中调用该事件.即使一个类声明了事件实例,并且您从该类派生了一个类,也无法在派生类中调用此事件.这是.NET的重要防呆功能.为什么这样?因为它可以保护您避免执行真正不需要的操作.这是控制反转的一种方式:您仅在某个声明的类中调用某些事件(最有可能的是,您根本不执行任何操作,因此也无法调用它们;最有可能的是,您正在谈论的不是您自己的事件),您只能用其他类型的代码处理该事件.相反,您确实需要在Click事件的处理程序中调用与该页面相关的某些方法或属性.顺便说一句,在WPF中最好使用其命令系统:IsVisible属性.您可以在XAML中编写Name属性,以使其为要操作的控件生成实例名称,并按名称分别设置每个实例的属性,但这是许多临时方法的方法在许多情况下,如果您拥有许多这样的控件,则很难维护.相反,您可以对这些控件进行分组并启用/禁用整个组.例如,您可以将某些控件放在同一Panel中.顺便说一句,您不需要禁用对隐藏(未选择)TabPage的控制:它们是不可见的,无法使用.

好吧,有些想法……不,我们并没有向您展示一些代码示例.如果您显示了一些代码示例并以此为基础提出了一些问题,我将更愿意.请注意,您的问题不仅以复杂的方式提出,而且还不够具体.没关系,您稍后可以询问后续问题.您可以随时使用改善问题".

—SA
The question is formulated clearly, I appreciate it, but it is way more complicated that it has to be. This approach is wrong. You should capture the essence of the real problem and try to reduce your application to something as simple as possible still having the same problem. Ask yourself: "in what simplest possible application I would have the same problem" and then describe it, even better, with a comprehensive code sample.

But this is just about time. I clearly understood the problem (or its comprehensible part). Basically, you are missing two important things.

First thing is: there is no such thing as "method on a page". A TabPage is just one of the controls, which is a member of some class, which can be your window class, some you custom or user control class, or something else. A method specifically related to this page can be a method of this class, that is, a static method, which can accept references to any control instances via its parameters. Or it can be an instance method of this class, which means that it can have the same or other parameter, plus one extra method, implicit one, "this" which is the instance of this class you can access inside the body of this method. That''s all. This is a key: you need to understand that the problem is somewhat artificial: 1) the scope of the method is the class which instance is a parent (direct + indirect) of many control instances; 3) control instance references can be passed to it as arguments.

There is another thing you are missing? Did you notice that in the title of the question you are asking about method, and at the end, you are asking about "firing an event"? Those are very different things. You cannot really "fire" and event (correct terminology is "invoke event"). More exactly, you can only invoke the event in the method of the type declaring this event. Even if one class declared event instance, and you derive a class from it, you cannot invoke this event in the derived class. This is an important fool-proof feature of .NET. Why so? Because it protects you from doing something which is really never needed. This is a mean of inversion of control: you only invoke some events in some declaring class (most likely, you don''t do it at all, so you cannot invoke them, too; most likely, you are talking about events which are not yours), you only handle the event in the code of other types. Instead, you really need to call some methods or properties related to the page in your handler of the Click events. By the way, in WPF its better to use its commanding system: https://msdn.microsoft.com/en-us/library/ms752308%28v=vs.110%29.aspx[^].

I called your problems "artificial" but they are not completely artificial; there are no the obstacles you imagined, but some problems still exist: there is always a problem to organize the code in a neat way. You mentioned enabling and disabling some control. Again, this is not "firing events" but is calling IsVisible properties. You can write the Name attributes in your XAML, to make it generating instance names for the controls you want to operate, and set the property of each instance individually, by name, but this would be way to much of ad-hoc approach in many cases, and quite poorly maintainable if you have many such controls. Instead, you can group those controls and enable/disable the whole group. For example, you could put some control in the same Panel. By the way, you don''t need to disable control on a hidden (non-selected) TabPage: they are invisible and cannot be used.

Well, some ideas… And no, we did not yest came to the point of showing you some code samples. I would prefer if you showed some code sample and asked some questions based on that. Note that your questions not only formulated in a complicated way, but also not specific enough for that. It''s all right, you can ask your follow-up questions later. You can use "Improve question" any time.

—SA


这是接口
 public interface ChildPageNav
    {
        /// <summary>
     /// For New Button Event
     /// </summary>
        void New();
}



现在,主窗口



Now the main window

 internal void btnAdd_Click(object obj, EventArgs e)
        {
            TabItem ti = TabWindow.SelectedItem as TabItem;
            Frame f = ti.Content as Frame;
            ChildPageNav page = f.Content as ChildPageNav;
           
            if (page != null) page.New();
        }

private void MetroWindow_Loaded(object sender, RoutedEventArgs e)
        {
            btnAdd.Click += new RoutedEventHandler(btnAdd_Click);
          
            Application.Current.MainWindow = this;
        }



最后是我使用界面的页面



Finally the page where I used the interface

public partial class MstAccMapping : System.Windows.Controls.Page, ChildPageNav
   {
 public MstAccMapping()
        {
            InitializeComponent();
        }

 public void New()
        {
            //Actions I needed to perform on button click
        }

}



我希望这是正确的方法,因为它可以正常工作.该界面充当窗口和页面之间的桥梁



I hope this is the right way as it works just fine. The interface acts as a bridge between the window and page


这篇关于如何从窗口单击事件访问页面中的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆