WPF intercept Binding Updates - c#

I would like to know if there is a mechanism to intercept all Bindings, so that I can suppress the updating on a specific condition?
Pseudo Code:
public class Utils
{
public void RegisterInterceptionOfBinding()
{
WpfBindingMechanism.OnSourceUpdating += SourceUpdating;
WpfBindingMechanism.OnTargetUpdating += TargetUpdating;
}
private void SourceUpdating(object sender, SourceUpdatingEventArgs args)
{
if (DoSomeMagicConditionChecking)
{
args.Cancel = true;
}
}
private void TargetUpdating(object sender, SourceUpdatingEventArgs args)
{
if (DoSomeMagicConditionChecking)
{
args.Cancel = true;
}
}
}
I am searching for a mechanism that works on ALL Bindings in the entire WPF Application.

You might be looking to use the TypeDescriptionProvider class.
Here is a forum post on MSDN that might answer your question:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/d8046807-ac1a-4d1f-81f2-6a2f93dab78a/intercept-binding-mechanism

Related

HttpModule and IoC in ASP.Net

So I had this problem where I absolutely needed to use the IoC of the solution I was working (and Am working) on but also needed to use an HttpModule to redirect the request before it even got in the container.
Well I found some ways to do it that weren't what I needed nor wanted.
I didn't want to add a dependency to a library to use it on just an HttpModule.
Well after fiddling a little with the module I got to a success.
It may not be pretty, it may cause some eye soreness, but it's working!
It will only actually use the EndRequest once and a simple boolean comparison isn't that costly. Also if for some reason the service isn't resolved propperly, it will use the EndRequest again. "Simple"!
I hope to have helped all the others that had the same problem as me!
public sealed class ChannelRedirectionModule : IHttpModule
{
private readonly Func<IChannelRedirectionService> _channelRedirectionService;
private static bool _firstCall = true;
public ChannelRedirectionModule()
{
_channelRedirectionService = DependencyResolver.Current.GetService<Func<IChannelRedirectionService>>();
}
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, e) =>
{
if (!_firstCall)
{
Redirect(sender, e);
}
};
context.EndRequest += (sender, e) =>
{
if (_firstCall)
{
Redirect(sender, e);
}
};
}
private void Redirect(object sender, EventArgs e)
{
var app = (sender as HttpApplication);
var channelRedirectionService = _channelRedirectionService();
if (channelRedirectionService == null)
{
_firstCall = true;
return;
}
_firstCall = false;
string redirectUrl = channelRedirectionService.GetRedirectAddressForChannelId(app.Request);
if (!string.IsNullOrEmpty(redirectUrl))
{
app.Response.Redirect(redirectUrl);
}
}
public void Dispose()
{
//there's realy nothing to be disposed here,
//but we're enforced to have this by the IHttpModule interface...
}
}

Updating GUI from different Class and Thread in c#

Im new to programming and just wanted to know if a solution for a problem I got is appropriate.
I wanted to write a status (string) into a textbox from a class which is creating a Socket and the class listens for data to receives (in an other thread).
This is what i did:
Create the Class whithin the Form.cs with a button click:
private void button_Create_Click(object sender, EventArgs e)
{
int port;
Int32.TryParse(textBox_Port.Text, out port);
ServerSocketClass serverSocket = new ServerSocketClass(port, this);
}
The ServerSocketClass looks like:
class ServerSocketClass
{
Socket ServerSocket;
Socket Accepted;
IPEndPoint LocalEndpoint;
int Port = 1337; // just for fun
Messenger MainForm;
public ServerSocketClass(int port, Messenger form)
{
MainForm = form;
if (port != 0)
Port = port;
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
LocalEndpoint = new IPEndPoint(IPAddress.Any, Port);
MainForm.writeToMessages("Binding Endpoint to Socket...");
ServerSocket.Bind(LocalEndpoint);
MainForm.writeToMessages("Starting ServerListener Thread...");
Thread ServerListenThread = new Thread(startListening);
ServerListenThread.Name = "ServerListenerThread";
ServerListenThread.Start();
}
private void startListening()
{
ServerSocket.Listen(5);
MainForm.writeToMessages("Whaiting for incoming connections...");
Accepted = ServerSocket.Accept();
whaitForData();
}
and to update the GUI in the forms class i created a delegate and a "update" method with an invoke:
public delegate void writeMessege(string message);
public writeMessege MessegeDelegate;
public void writeToMesseges(string messege)
{
if (InvokeRequired)
{
this.Invoke(MessegeDelegate, new object[] { messege });
return;
}
textBox_Messeges.AppendText("SYSTEM: " + messege + "\n");
}
It works, but I wanted to know if this is a "valid" way to do it or if I should go to the developer hell ;-)
thanks in advance
Locke
It's a perfectly valid way to do that, although whether it is "right" depends very much on the context - how often you call it, what you want to do inside it, and the code that you need to call it. There are many different ways of doing it without invoke, but there is nothing wrong with using InvokeRequired/Invoke - that's what it's there for. You could just use an update method that invokes itself, which is almost the same as your code, but slightly less verbose:
public void WriteMessages(string message)
{
if (InvokeRequired)
{ this.Invoke(new Action<string>(WriteMessages), new object[] { message }); }
else
{ textBox_Messages.AppendText("SYSTEM: " + message + "\n"); }
}
There are a lot of posts already on Invoke/InvokeRequired. As a starting point, check:
Isn't blindly using InvokeRequired just bad practice?
I had a similar situation, where I had a class that was called from other classes with many separate threads and I had to update one specific form from all these other threads. So creating a delegate and an event in the class with a handler in the form was the answer. So I wanted to share it as it seems simpler (even if not necessarily a better solution).
The solution that worked for me:
I created an event in the class I wanted to do the update on another form. (First of course I instantiated the form (called SubAsstToolTipWindow) in the class.
Then I used this event (ToolTipShow) to create an event handler on the form I wanted to update the label on. Worked like a charm.
I used this description to devise my own code below in the class that does the update:
public static class SubAsstToolTip
{
private static SubAsstToolTipWindow ttip = new SubAsstToolTipWindow();
public delegate void ToolTipShowEventHandler();
public static event ToolTipShowEventHandler ToolTipShow;
public static void Show()
{
// This is a static boolean that I set here but is accessible from the form.
Vars.MyToolTipIsOn = true;
if (ToolTipShow != null)
{
ToolTipShow();
}
}
public static void Hide()
{
// This is a static boolean that I set here but is accessible from the form.
Vars.MyToolTipIsOn = false;
if (ToolTipShow != null)
{
ToolTipShow();
}
}
}
Then the code in my form that was updated:
public partial class SubAsstToolTipWindow : Form
{
public SubAsstToolTipWindow()
{
InitializeComponent();
// Right after initializing create the event handler that
// traps the event in the class
SubAsstToolTip.ToolTipShow += SubAsstToolTip_ToolTipShow;
}
private void SubAsstToolTip_ToolTipShow()
{
if (Vars.MyToolTipIsOn) // This boolean is a static one that I set in the other class.
{
// Call other private method on the form or do whatever
ShowToolTip(Vars.MyToolTipText, Vars.MyToolTipX, Vars.MyToolTipY);
}
else
{
HideToolTip();
}
}
long time ago, but I wanted you all know how I finally solved this to my full satisfaction (solved it with Events - of course ;-)):
I defined an EventArgs to pass all the Information I wanted to pass:
public class IncomingMessageEventArgs : EventArgs
{
private Message _message;
public Message Message
{
get
{
return _message;
}
}
public IncomingMessageEventArgs(Message message)
{
_message = message;
}
}
On the Class that publishes the information (to the WPF - Form) define the Event and its Handler:
public delegate void IncomingMessageEventHandler(object sender, IncomingMessageEventArgs e);
public event IncomingMessageEventHandler IncomingMessageEvent;
protected void OnIncomingMessageEvent(IncomingMessageEventArgs e)
{
if (IncomingMessageEvent != null)
IncomingMessageEvent(this, e);
}
and of course Raise the event, if the WPF Form needs to be updated (also on the "information sending class"):
OnIncomingMessageEvent(new IncomingMessageEventArgs(message));
on the WPF Class you need to listen to the events but first define a EventHandler because your information comes from a differen Thread!! :
private delegate void writeMessageToChatEventHandler(object sender, IncomingMessageEventArgs e);
now we write our method witch will handle the raised event:
// Write to Chat
private void writeMessageToChat(object sender, IncomingMessageEventArgs e)
{
try
{
if (!Dispatcher.CheckAccess())
{
Dispatcher.Invoke(new writeMessageToChatEventHandler(writeMessageToChat), new object[] { sender, e } );
return;
}
textBox_Chat.AppendText(e.Message.getFormatedMessageText() + "\n");
}
catch (Exception ex)
{
writeLogToChat(this, new IncomingLogEventArgs("ERROR: " + ex.Message));
}
}
and finally, we need to subscribe to the event of course (the first method, you can ignore, its just to meet the MS Nameing conventions:
private void ClientSocket_IncomingMessageEvent(object sender, IncomingMessageEventArgs e)
{
writeMessageToChat(sender, e);
}
ClientSocket.IncomingMessageEvent += ClientSocket_IncomingMessageEvent;
Hopefully I made this understandable :P
Thanks to all the people how helped me!
bye

Redirecting Events to handlers inside custom controls

I have mad a custom control. and i need to redirect the Event handler. i have cut the code down dramatically to try and articulate what im trying to do.
public class RemoteDesktop : WindowsFormsHost
{
public event OnConnectingEventHandler OnConnecting;
public delegate void OnConnectingEventHandler(object sender, EventArgs Arguments);
public event OnDisconnectingEventHandler OnDisconnecting;
public delegate void OnDisconnectingEventHandler(Object sender, IMsTscAxEvents_OnDisconnectedEvent Arguments);
private AxMsRdpClient7NotSafeForScripting RDPUserControl = new AxMsRdpClient7NotSafeForScripting();
public RemoteDesktop()
{
this.RDPUserControl.BeginInit();
this.RDPUserControl.SuspendLayout();
base.Child = RDPUserControl;
this.RDPUserControl.ResumeLayout();
this.RDPUserControl.EndInit();
}
}
public class RemoteDesktopViewModel
{
public RemoteDesktopViewModel()
{
RemoteDesktop newRDC = new RemoteDesktop();
newRDC.OnConnecting += new RemoteDesktop.OnConnectingEventHandler(newRDC_OnConnecting);
}
void newRDC_OnConnecting(object sender, EventArgs Arguments)
{
//DoStuff
}
}
basically it all works, i can connect and disconnect to the remote computer however i cannot get the fired events to occur in my view model.
Can anyone help me figure out how i can point my events correctly.
Thank you.
Thanks to some help i have the resolution
Step 1:
Declare delegates outside the class (within the namespace)
Step 2:
Declare the events to be called for the control.
Step 3: use the event handlers of the controls to reise the delegates you created
Completed Code
public delegate void OnConnectingEventHandler(object sender, EventArgs Arguments);
public delegate void OnDisconnectingEventHandler(Object sender,IMsTscAxEvents_OnDisconnectedEvent Arguments);
public class RemoteDesktop : WindowsFormsHost
{
public event OnConnectingEventHandler IsConnecting;
public event OnDisconnectingEventHandler IsDisconnecting;
private AxMsRdpClient7NotSafeForScripting RDPUserControl = new AxMsRdpClient7NotSafeForScripting();
public RemoteDesktop()
{
this.RDPUserControl.BeginInit();
this.RDPUserControl.SuspendLayout();
base.Child = RDPUserControl;
this.RDPUserControl.ResumeLayout();
this.RDPUserControl.EndInit();
RDPUserControl.OnConnecting += RemoteDesktop_OnConnecting;
RDPUserControl.OnDisconnected += RDPUserControl_OnDisconnected;
}
void RDPUserControl_OnDisconnected(object sender, IMsTscAxEvents_OnDisconnectedEvent e)
{
IsDisconnecting(sender, e);
}
void RemoteDesktop_OnConnecting(object sender, EventArgs Arguments)
{
IsConnecting(sender, Arguments);
}
}
public class RemoteDesktopViewModel
{
public RemoteDesktopViewModel()
{
RemoteDesktop newRDC = new RemoteDesktop();
newRDC.IsConnecting += new RemoteDesktop.OnConnectingEventHandler(newRDC_OnConnecting);
}
void newRDC_OnConnecting(object sender, EventArgs Arguments)
{
//DoStuff
}
}
//at the constractor of the class
OnConnecting+=RDC_OnConnecting;
then you can write your logic in method:newRDC_OnConnecting. make sure OnConnectingEventHandler have same method signatures with newRDC_OnConnecting.

Use external resources within an event handler

Consider the following program:
class Program
{
static void Main(string[] args)
{
var MyEventThrower = new EventThrower();
var log= new List<string>();
log.Add("Log Initialized");
MyEventThrower.Event += LogEvent;
MyEventThrower.RaiseEvent();
foreach (var item in log)
{
Console.WriteLine(item);
}
}
static void LogEvent(object sender, EventArgs e)
{
log.Add(sender.ToString()); //obviously doesn't work,
//but this is the sort of
//behavior I want to achieve.
}
}
for reference:
public delegate void EventHandler(object sender, EventArgs e)
public class EventThrower
{
public event EventHandler Event;
protected virtual void OnEvent(EventArgs e)
{
if (Event!= null)
{
Event(this, e);
}
}
public void RaiseEvent()
{
OnEvent(EventArgs.Empty);
}
}
Edit: My problem here is that log is not within the same context as the event handler. I see now that I can fix that by making it a static class member.
The easiest option is to use a lambda to close over the list:
var MyEventThrower = new EventThrower();
var log= new List<string>();
log.Add("Log Initialized");
MyEventThrower.Event += (sender, args) => log.Add(sender.ToString());
MyEventThrower.RaiseEvent();
foreach (var item in log)
{
Console.WriteLine(item);
}
I'm not sure if you need to use your log variable/list for anything else, so I'm making the assumption you only have to facilitate logging in the way you designed your code.
I'd suggest something like the following:
static void Main()
{
var logger = new Logger();
logger.Log("Log Initialized");
var MyEventThrower = new EventThrower();
MyEventThrower.Event += (sender, _) => logger.Log(Convert.ToString(sender));
MyEventThrower.RaiseEvent();
}
public class Logger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
This let's you wrap the implementation detail inside of a logger class. You could even extend this further by creating your own sort of ILogger interface and making different Logger implementations (i..e one for a file, one for console etc). If you're only ever planning on writing to the console, this is potentially overkill.
The one thing I do like about using a class to wrap the actual logging is that the implementation is in one spot. If you ever decide you want all your log messages to have "DEBUG: " prepended to the message you're logging, you only need to do it in one spot.
The other thing I like about this compared to the original solution is that you're not adding things to a list and then iterating over them again to print out information. You're doing it as the event is triggered. This will save on memory usage too (i.e. not holding all of your log messages in a list before you're ready to output them). If I misunderstood why you actually have that log list of strings, then I apologize for this.

Question on threading in C#

I have a Windows Forms application at the moment, and I want to create a new thread and run a method on another class that accepts an input.
For example
public partial class Form1: Form {
SerialPort serialInput;
// I want to create a new thread that will pass the parameter serialInput into the method
// SMSListener on another class and run the method contionously on the background.
}
class SMS
{
public void SMSListener(SerialPort serial1)
{
serial1.DataReceived += port_DataRecieved;
}
private void port_DataRecieved(object sender, SerialDataReceivedEventArgs e)
{
// Other codes
}
}
How do I perform this in C#? I have seen numerous examples on the web, and most of them run the method on the same class with no parameters, but none that suits my requirements.
Perhaps a Background Worker could help you?
It is a bit hard to understand what you are aiming at.
public class Runner
{
private readonly BackgroundWorker _worker = new BackgroundWorker();
public Runner()
{
_worker.DoWork += WorkerDoWork;
}
public void RunMe(int payload)
{
_worker.RunWorkerAsync(payload);
}
static void WorkerDoWork(object sender, DoWorkEventArgs e)
{
var worker = sender as BackgroundWorker;
while (true)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
// Work
System.Threading.Thread.Sleep((int)e.Argument);
}
}
}
I am not an expert on Multithreading but to the best of my knowledge you can only start threads on methods that accept an object parameter and return void. So in order to achieve that for your problem (don't shoot me down if there is a better approach!) I would do something like
public partial class Form1: Form {
SerialPort serialInput;
// I want to create a new thread that will pass the parameter serialInput into the method
// SMSListener on another class and run the method contionously on the background.
SMS sms = new SMS();
Thread t = new Thread(sms.SMSListenerUntyped);
t.Start(serialInput);
}
class SMS
{
public void SMSListenerUntyped(object serial1) {
if (serial1 is SerialPort) //Check if the parameter is correctly typed.
this.SMSListener(serial1 as SerialPort);
else
throw new ArgumentException();
}
public void SMSListener(SerialPort serial1)
{
serial1.DataReceived += port_DataRecieved;
}
private void port_DataRecieved(object sender, SerialDataReceivedEventArgs e)
{
// Other code.
}
How about just use the ThreadPool directly with a anonymous method allowing you to access your surrounding locals?
public void OnButtonClick(object sender, EventArgs e)
{
SerialPort serialInput = this.SerialInput;
System.Threading.ThreadPool.QueueUserWorkItem(delegate
{
SmsListener listener = new SmsListener(serialInput);
});
}

Categories