I'm attempting to implement an adorner for a PasswordBox to add watermark functionality. I'm basing it on the project at http://sladorner.codeplex.com/. I've gotten the watermark implementation working in a sandbox application, but I'm running into issues when I attempt to add this to a class library.
When the line that sets _Popup.Child is executed, I get the exception "Error HRESULT E_FAIL has been returned from a call to a COM component." Is there a solution for this (or maybe a completely different way around the issue of watermarking a PasswordBox)?
public class PasswordBoxWatermarkAdorner : Control
{
private Border _ContentBorder;
private TextBlock _WatermarkTextBlock;
private PasswordBox _AssociatedElement;
private Popup _Popup;
private string _WatermarkText;
public PasswordBoxWatermarkAdorner(PasswordBox associatedElement, string watermarkText)
{
this.DefaultStyleKey = typeof(PasswordBoxWatermarkAdorner);
_AssociatedElement = associatedElement;
_WatermarkText = watermarkText;
_Popup = new Popup
{
Child = this,
IsOpen = true
};
_Popup.LayoutUpdated += _Popup_LayoutUpdated;
}
Related
I'm trying to implement the a Balloon Notification to appear when a button is clicked however I keep receiving a specific error:
An object reference is required for the non-static field, method, or property
'TaskbarIcon.ShowBalloonTip(string, string, BalloonIcon)
I'm using the library Hardcodet.Wpf.TaskbarNotification;
The Method is
class NotifyIcon
{
public static void ShowStandardBalloon()
{
string title = "WPF NotifyIcon";
string text = "This is a standard balloon";
TaskbarIcon.ShowBalloonTip(title, text, BalloonIcon.Error);
}
}
and is called:
private void Button_Click(object sender, RoutedEventArgs e)
{
NotifyIcon ST = new NotifyIcon();
ST.ShowStandardBalloon();
}
Error is appearing under TaskbarIcon.ShowBalloonTip.
I've tried changing to public static void in the Notify Icon class however that didn't resolve anything.
You need to call the ShowBalloonTip on and instance of TaskbarIcon
TaskbarIcon TBIcon = new TaskbarIcon()
string title = "WPF NotifyIcon";
string text = "This is a standard balloon";
TBIcon.ShowBalloonTip(title, text, BalloonIcon.Error);
I'm trying to access a native Wpf control property within the UI test framework (MS UI Tests). My specific issue is that, when I try accessing a WpfButton control property (e.g., IsVisible) using the function call WpfButtonObject.GetProperty("IsVisible"), the exception "System.NotSupportedExceptions" occurs. I'm able to see this WpfButton property using Snoop; so, I'm wondering if the GetProperty call is correct? Please see my related code below. Thanks for any insight.
UIMap.cs: Test function for a pressing a WpfButton. Please note the call uIButton.GetPropery("IsVisible"). This is where the exception occurs:
public void PressButtonTest()
{
WpfButton uIButton = this.UIMainWindowWindow.UIButtonButton;
object state = uIButton.GetProperty("IsVisible"); // Throws SystemNotSupportedException exception
bool stateBool = (bool)state;
Assert.IsTrue(stateBool, "Button is visible");
PressButton();
}
UIMap.Designer.cs: WpfButton property:
public WpfButton UIButtonButton
{
get
{
if ((this.mUIButtonButton == null))
{
this.mUIButtonButton = new WpfButton(this);
#region Search Criteria
this.mUIButtonButton.SearchProperties[WpfButton.PropertyNames.AutomationId] = "button";
this.mUIButtonButton.WindowTitles.Add("MainWindow");
#endregion
}
return this.mUIButtonButton;
}
}
Here's what I've done:
Point point;
bool isClickable = uIButton.TryGetClickablePoint(out point);
Assert.IsTrue(isClickable, "No clickable point was found, button not visible.");
By the way, your message in your Assert (2nd parameter) is inaccurate because it's only used on fail... in your case, when the button would not be visible. So in your output it would say "Button is visible" on failure when in fact it was not.
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I have this code in the main wpf window:
private void ButtonChangePermissions_Click(object sender, RoutedEventArgs e)
{
if (ComboBoxSelectedProfile.SelectedIndex != -1)
{
ChangePermissionsWindow cpWindow = new ChangePermissionsWindow { parent = this };
cpWindow.Show();
}
else
{
MessageBox.Show("Please choose a profile first.");
}
}
This is the child wpf window code:
public partial class ChangePermissionsWindow : Window
{
private readonly string dbConnectionString = Properties.Settings.Default.dbConnectionString;
public postLoginWindow parent { get; set; }
public ChangePermissionsWindow()
{
InitializeComponent();
ComboBoxValuesToShow();
}
private void ComboBoxValuesToShow()
{
using (SqlConnection connection = new SqlConnection(dbConnectionString))
{
try
{
connection.Open();
if (TableFunctions.doesTableExist("ProfilePermissions", dbConnectionString))
{
string selectQuery = "SELECT Permissions from ProfilePermissions where ProfileName = #ProfileName";
using (SqlCommand command = new SqlCommand(selectQuery, connection))
{
command.Parameters.AddWithValue("#ProfileName", parent.ComboBoxSelectedProfile.Text);//This line produces the Null reference error
...Does not matter from here
}
For some reason the line:
command.Parameters.AddWithValue("#ProfileName", parent.ComboBoxSelectedProfile.Text)
causes a NullReferenceException.
This is the exception documentation:
System.NullReferenceException: Object reference not set to an instance
of an object.
at WpfApplication1.Windows.ChangePermissionsWindow.ComboBoxValuesToShow()
in c:\Users\Censored\Documents\Visual Studio
2013\Projects\WpfApplication1\WpfApplication1\Windows\WindowChangePermissions.xaml.cs:line 38}
System.Exception {System.NullReferenceException
I will appreciate your help very much!
At a very high-level using the Object initialization syntax follows these steps...
Create an instance of the desired class by calling the appropriate constructor
Call all of the listed property setters
Return the newly initialized object
ComboBoxValuesToShow is called from the constructor but based on the listed steps the parent property (which is used in the method) is not set until after the constructor returns, because the property setters are not called until after the instance is created. Therefore the parent property will always be null in this case.
There are a couple of ways that come to mind to solve this...
If you want to use the parent property in the constructor then pass the value into the constructor and initialize the property internally.
Or
Make the ComboBoxValuesToShow method accessible from the parent window and move the call to ComboBoxValuesToShow from the constructor to the event handler in the parent window.
I am trying to display a custom dialog box multiple times using the following code:
TestWindow newTestWindow = new TestWindow(test);
newTestWindow.Owner = this;
newTestWindow.ShowDialog();
And I get the following exception when running the code above for the 2nd time:
Specified element is already the logical child of another element. Disconnect it first.
Chances are you are trying to display the same element in both dialogs (maybe the test parameter)? You would need to disconnect the element from the dialog when it's closed, so that it can be used in any subsequent dialogs.
Works fine for me:
public partial class MainWindow : Window
{
private Test _newTestWindow;
public MainWindow()
{
InitializeComponent();
Loaded += new RoutedEventHandler(OnLoaded);
}
private void OnLoaded( object sender, RoutedEventArgs e )
{
_newTestWindow = new Test { Owner = this };
_newTestWindow.ShowDialog();
_newTestWindow = new Test { Owner = this };
_newTestWindow.ShowDialog();
}
}
I am trying to unit test my WPF databindings using the test suit provided by Microsoft Team System. I would like to be able to test the bindings without showing the window because most of my tests will be for user controls and not actually on a window. Is this possible or is there a better way to do it? The code below works if I show the window, but if I don't, the bindings don't update.
Window1_Accessor target = new Window1_Accessor();
UnitTestingWPF.Window1_Accessor.Person p = new UnitTestingWPF.Window1_Accessor.Person() { FirstName = "Shane" };
Window1 window = (target.Target as Window1);
window.DataContext = p;
//window.Show(); //Only Works when I actually show the window
//Is it possible to manually update the binding here, maybe? Is there a better way?
Assert.AreEqual("Shane", target.textBoxFirstName.Text); //Fails if I don't Show() the window because the bindings aren't updated
While looking for a solution to convert WPF binding errors into exception, I figured out that it can also be used in a unit test project.
The technique is very simple:
Derive a TraceListener that throws instead of logging
Add that listener to PresentationTraceSources.DataBindingSource
Please see the complete solution on GitHub, it includes a unit test project.
Shane, if what you're really worried about is a binding breaking silently, you should look at redirecting the binding traces to somewhere you can examine. I'd start here:
http://blogs.msdn.com/mikehillberg/archive/2006/09/14/WpfTraceSources.aspx
Other than that, I agree with Gishu that bindings aren't good candidates for unit testing, mainly due to the automagic going on that Gishu mentioned in the "Epilogue". Instead focus on making sure the underlying class behaves correctly.
Note, too, that you can get even more robust traces using the PresentationTraceSources class:
http://msdn.microsoft.com/en-us/library/system.diagnostics.presentationtracesources.aspx
Hope that helps!
Eyeball it.
This kind of declarative markup rarely breaks.. unless someone goes in manual and screws it up. Even then, you can fix it within minutes. IMHO the cost of writing such tests far outweigh the benefits.
Update[Dec3,08]: Alrighty then.
The test is just testing that the textbox has the value "FirstName" as the Path property of the binding. If I change/refactor FirstName to JustName in the actual data source object, the test would still pass since it is testing against an anonymous type. (Green test when code broken - TDD Antipattern: The Liar)
If your aim is to verify that FirstName has been specified in XAML,
Assert.AreEqual("FirstName", txtBoxToProbe.GetBindingExpression(TextBox.TextProperty).ParentBinding.Path.Path);
If you really must catch broken bindings via unit tests (and don't want to show the UI), use the real data source... struggled for a while and came up with this.
[Test]
public void TestTextBoxBinding()
{
MyWindow w = new MyWindow();
TextBox txtBoxToProbe = w.TextBox1;
Object obDataSource = w; // use 'real' data source
BindingExpression bindingExpr = BindingOperations.GetBindingExpression(txtBoxToProbe, TextBox.TextProperty);
Binding newBind = new Binding(bindingExpr.ParentBinding.Path.Path);
newBind.Source = obDataSource;
txtBoxToProbe.SetBinding(TextBox.TextProperty, newBind);
Assert.AreEqual("Go ahead. Change my value.", txtBoxToProbe.Text);
}
Epilogue:
There's some real covert stuff happening in the call to Window.Show(). It somehow magically sets up the DataItem property after which data binding starts working.
// before show
bindingExpr.DataItem => null
bindingExpr.Status => BindingStatus.Unattached
// after show
bindingExpr.DataItem => {Actual Data Source}
bindingExpr.Status => BindingStatus.Active
Once the Binding is Active, I guess you can force textbox updates via code like this..
txtBoxToProbe.GetBindingExpression(TextBox.TextProperty).UpdateTarget();
Once again, I voice my reluctance against this approach. Getting NUnit to run in STA was a pain..
Combining advice I came across in a number of SO posts I wrote the following class which works very well to test WPF bindings.
public static class WpfBindingTester
{
/// <summary>load a view in a hidden window and monitor it for binding errors</summary>
/// <param name="view">a data-bound view to load and monitor for binding errors</param>
public static void AssertBindings(object view)
{
using (InternalTraceListener listener = new InternalTraceListener())
{
ManualResetEventSlim mre = new ManualResetEventSlim(false);
Window window = new Window
{
Width = 0,
Height = 0,
WindowStyle = WindowStyle.None,
ShowInTaskbar = false,
ShowActivated = false,
Content = view
};
window.Loaded += (_, __) => mre.Set();
window.Show();
mre.Wait();
window.Close();
Assert.That(listener.ErrorMessages, Is.Empty, listener.ErrorMessages);
}
}
/// <summary>Is the test running in an interactive session. Use with Assume.That(WpfBindingTester.IsAvailable) to make sure tests only run where they're able to</summary>
public static bool IsAvailable { get { return Environment.UserInteractive && Process.GetCurrentProcess().SessionId != 0; } }
private class InternalTraceListener : TraceListener
{
private readonly StringBuilder _errors = new StringBuilder();
private readonly SourceLevels _originalLevel;
public string ErrorMessages { get { return _errors.ToString(); } }
static InternalTraceListener() { PresentationTraceSources.Refresh(); }
public InternalTraceListener()
{
_originalLevel = PresentationTraceSources.DataBindingSource.Switch.Level;
PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Error;
PresentationTraceSources.DataBindingSource.Listeners.Add(this);
}
public override void Write(string message) {}
public override void WriteLine(string message) { _errors.AppendLine(message); }
protected override void Dispose(bool disposing)
{
PresentationTraceSources.DataBindingSource.Listeners.Remove(this);
PresentationTraceSources.DataBindingSource.Switch.Level = _originalLevel;
base.Dispose(disposing);
}
}
}
you can try Guia.
With it you can unit-test your UserControl and check if the data binding is correct. You have to show the window though.
Here is an example. It starts a new instance of your UserControl and sets its DataContext and then checks if the textbox is set to the right value.
[TestMethod]
public void SimpleTest()
{
var viewModel = new SimpleControlViewModel() {TextBoxText = "Some Text"};
customControl = CustomControl.Start<SimpleUserControl>((control) => control.DataContext = viewModel);
Assert.AreEqual("Some Text", customControl.Get<TextBox>("textbox1").Value);
customControl.Stop();
}