2013-10-03 182 views
0

我想按照預期使用工具提示。但是當發生錯誤時,我想更改它們以顯示錯誤消息,然後當錯誤得到解決時,將它們改回。WPF爲工具提示創建附加屬性

所以我創建了一個附加的屬性來保存工具提示。我將工具提示分配給附加屬性,然後使用樣式將其複製到工具提示屬性。如果出現錯誤,則樣式會將工具提示設置爲錯誤消息。

所以設置在提示錯誤信息的觸發條件爲:

<Trigger Property="Validation.HasError" 
       Value="true"> 
<Setter Property="BorderBrush" 
       Value="{DynamicResource controls-errorBorderBrush}" /> 
<Setter Property="ToolTip" 
       Value="{Binding RelativeSource={x:Static RelativeSource.Self}, 
    Path=(Validation.Errors)[0].ErrorContent}" /> 
</Trigger> 

這似乎很容易(和作品)

當錯誤被修正,我將其設置回(這並未」將不起作用):

<Trigger Property="Validation.HasError" 
Value="false"> 
<Setter Property="ToolTip" 
    Value="{Binding Path=(wpfMisc:myCtrl.tooltipValue)}" /> 
</Trigger> 

而在XAML文件中我有:

<TextBox Text="this is a textbox with a myMisc based tooltip" 
Name="txtTooltip2" 
wpfMisc:myCtrl.tooltipValue="Tooltip Test tooltip" /> 

所以當然,這個問題很可能出現在我附加的屬性中,因爲它似乎沒有正確保存信息。下面是該代碼:

public static string GettooltipValue(DependencyObject obj) 
{ 
string value = obj.GetValue(tooltipValueProperty).ToString() ; 
value = value.trimNull() ; // extension method to insure at least an empty string 
return value ; 
} 

public static void SettooltipValue(DependencyObject obj, string value) 
{ 
obj.SetValue(tooltipValueProperty, value.trimNull()); 
} 

public static readonly DependencyProperty tooltipValueProperty = 
DependencyProperty.RegisterAttached("tooltipValue", 
typeof(string), 
typeof(myCtrl), 
new UIPropertyMetadata(string.Empty)); 

所以我的猜測是,我需要用的東西在UIPropertyMetaData不同,但不知道我會用什麼。或者我的整個方法錯了?

我想爲所有數據字段提供特定於數據的工具提示。

我確實在錯誤期間通過將工具提示移動到標記屬性工作,但我不想讓它以這種方式工作,因爲我知道當其他代碼想要使用以某種特殊方式標記。

而且,我知道的一些代碼很冗長 - 只是調試的副作用...

而在另一myCtrl依賴屬性工作得很好,所以我知道的xmlns等引用正確。

在進一步的研究中,我在輸出窗口中發現了以下內容: System.Windows.Data錯誤:17:無法從''(type'layoutSettingsViewModel')獲取'tooltipValue'值(類型'String')。 BindingExpression:路徑=(0); DataItem ='layoutSettingsViewModel'(HashCode = 46457861);目標元素是'TextBox'(Name ='');目標屬性是'工具提示'(類型'對象')InvalidCastException:'System.InvalidCastException:無法強制'類型'client.Models.layoutSettings.layoutSettingsViewModel'類型的對象類型'System.Windows.DependencyObject'。

layoutSettingsViewModel是xaml視圖。所以我認爲觀點本身在某種程度上獲得了價值,而不是控制......不過,我不確定 - 我猜你們中的一個人確切知道它是什麼意思,爲什麼......我討厭試圖加快速度新語言...

無論如何,任何幫助和/或建議表示讚賞。

+0

你得到在輸出窗口任何綁定錯誤時驗證.HasError設置爲false?以及如何和你在哪裏設置wpfMisc:myCtrl.tooltipValue也可以分享你對你所申請這些觸發器控制? – Nitin

+0

兩件事我會爲開始,首先嚐試只返回 obj.GetValue不需要所有其他代碼,因爲現在WPF(C#)可能會優化您的附加屬性代碼和它通常預計的默認實現這可能不是這樣的(但只是要確定), 其次,加回叫你DP,看看值實際上 變化,當和你以外,讓我知道ü想出什麼樣的。 –

+0

尼特,我有代碼,但由於某種原因,它沒有顯示。就是現在。我一直在測試一個簡單的文本框,雖然我想用它來處理任何數據輸入。 – JustMeToo

回答

0

我創建了類似的功能,但對於Button控件。我會爲您提供我的工作代碼,您只需用您想要使用的任何控制器替換Button即可。我不得不創建一個AttachedProperty殘疾人ToolTip消息,另一個是「記住」原始值:

private static readonly DependencyPropertyKey originalToolTipPropertyKey = DependencyProperty.RegisterAttachedReadOnly("OriginalToolTip", typeof(string), typeof(ButtonProperties), new FrameworkPropertyMetadata(default(string))); 

/// <summary> 
/// Contains the original Button.ToolTip value to display when the Button.IsEnabled property value is set to true. 
/// </summary> 
public static readonly DependencyProperty OriginalToolTipProperty = originalToolTipPropertyKey.DependencyProperty; 

/// <summary> 
/// Gets the value of the OriginalToolTip property. 
/// </summary> 
/// <param name="dependencyObject">The DependencyObject to return the OriginalToolTip property value from.</param> 
/// <returns>The value of the OriginalToolTip property.</returns> 
public static string GetOriginalToolTip(DependencyObject dependencyObject) 
{ 
    return (string)dependencyObject.GetValue(OriginalToolTipProperty); 
} 

/// <summary> 
/// Provides Button controls with an additional tool tip property that only displays when the Button.IsEnabled property value is set to false. 
/// </summary> 
public static DependencyProperty DisabledToolTipProperty = DependencyProperty.RegisterAttached("DisabledToolTip", typeof(string), typeof(ButtonProperties), new UIPropertyMetadata(string.Empty, OnDisabledToolTipChanged)); 

/// <summary> 
/// Gets the value of the DisabledToolTip property. 
/// </summary> 
/// <param name="dependencyObject">The DependencyObject to return the DisabledToolTip property value from.</param> 
/// <returns>The value of the DisabledToolTip property.</returns> 
public static string GetDisabledToolTip(DependencyObject dependencyObject) 
{ 
    return (string)dependencyObject.GetValue(DisabledToolTipProperty); 
} 

/// <summary> 
/// Sets the value of the DisabledToolTip property. 
/// </summary> 
/// <param name="dependencyObject">The DependencyObject to set the DisabledToolTip property value of.</param> 
/// <param name="value">The value to be assigned to the DisabledToolTip property.</param> 
public static void SetDisabledToolTip(DependencyObject dependencyObject, string value) 
{ 
    dependencyObject.SetValue(DisabledToolTipProperty, value); 
} 

/// <summary> 
/// Adds ro removes event handlers to the Button control that updates the Button.ToolTip value to the DisabledToolTip property value when the Button.IsEnabled property value is set to false. 
/// </summary> 
/// <param name="dependencyObject">The Button object.</param> 
/// <param name="e">The DependencyPropertyChangedEventArgs object containing event specific information.</param> 
public static void OnDisabledToolTipChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
{ 
    Button button = dependencyObject as Button; 
    if (button != null && e.OldValue != e.NewValue) button.IsEnabledChanged += Button_IsEnabledChanged; 
    else if (e.OldValue != null && e.NewValue == null) button.IsEnabledChanged -= Button_IsEnabledChanged; 
} 

private static void Button_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) 
{ 
    Button button = sender as Button; 
    if (GetOriginalToolTip(button) == null) button.SetValue(originalToolTipPropertyKey, button.ToolTip.ToString()); 
    button.ToolTip = (bool)e.NewValue ? GetOriginalToolTip(button) : GetDisabledToolTip(button); 
} 

它這樣使用:

<Button ToolTip="Normal ToolTip text to display" 
    Attached:ButtonProperties.DisabledToolTip="Text to automatically display when 
    Button is disabled"> 
+0

我假設你的意思是該行156應該是 - =代替+ =(還是我缺少明顯的東西?) – JustMeToo

+0

這將是第二個如果OnDisabledToolTipChanged(因爲我重新格式化代碼,行#秒不匹配。)此外,我無法獲取工具提示,以顯示禁用按鈕的時間 - 即使我只是使用常規工具提示。我錯過了別的嗎? – JustMeToo

+0

哈耶,有關' - ='的好地方,謝謝!它應該工作,但你必須同時設置常規'ToolTip' *和*了'DisabledToolTip'屬性...它爲我工作。把一個斷點在'Button_IsEnabledChanged'處理程序,看它是否被調用......如果沒有,你可能有一些問題,你的'AttachedProperty'類。 – Sheridan

0

對於任何人誰在乎,這裏是基本邏輯 - 建立在Sheridan共享的代碼上。我知道這可以做得更簡潔,等等。但是,這使得更新的WPF開發人員可以輕鬆開始瞭解事情的工作方式。

這裏是XAML風格 - 其可被用於支持一個工具提示和數據的任何控制:

<Style TargetType="TextBox"> 
<Style.Triggers> 
    <Trigger Property="Validation.HasError" 
         Value="true"> 
     <!-- We have an error, set the ErrorToolTip attached property to 
     the error. When the error is no more, it is automatically set 
     back to the original value (blank) so no need for a 2nd trigger --> 
     <Setter Property="wpfMisc:myCtrl.ErrorToolTip" 
         Value="{Binding RelativeSource={x:Static RelativeSource.Self}, 
     Path=(Validation.Errors)[0].ErrorContent}" /> 

    </Trigger> 

</Style.Triggers> 
</Style> 

而這裏是可以(使用myCtrl這裏),其保持被添加到類代碼依賴屬性/屬性:

/// <summary> 
/// Holds the default Tooltip value. OnMyToolTipChanged used to set ToolTip 
/// </summary> 
public static DependencyProperty MyToolTipProperty = DependencyProperty.RegisterAttached("MyToolTip", typeof(string), typeof(myCtrl), new UIPropertyMetadata(string.Empty, OnMyToolTipChanged)); 

/// <summary> 
/// Gets the value of the MyToolTip property. 
/// </summary> 
/// <param name="dependencyObject">The DependencyObject to return the MyToolTip property value from.</param> 
/// <returns>The value of the MyToolTip property.</returns> 
public static string GetMyToolTip(DependencyObject dependencyObject) 
{ 
    return (string)dependencyObject.GetValue(MyToolTipProperty); 
} 

/// <summary> 
/// Sets the value of the MyToolTip property. 
/// </summary> 
/// <param name="dependencyObject">The DependencyObject to set the MyToolTip property value of</param> 
/// <param name="value">The value to be assigned to the MyToolTip property.</param> 
public static void SetMyToolTip(DependencyObject dependencyObject, string value) 
{ 
    dependencyObject.SetValue(MyToolTipProperty, value); 
} 

/// <summary> 
/// Initially blank, set by style when an error occures (or goes away). Uses OnErrorToolTipChanged to update ToolTip. 
/// </summary> 
public static DependencyProperty ErrorToolTipProperty = DependencyProperty.RegisterAttached("ErrorToolTip", typeof(string), typeof(myCtrl), new UIPropertyMetadata(string.Empty, OnErrorToolTipChanged)); 

/// <summary> 
/// Gets the value of the ErrorToolTip property. 
/// </summary> 
/// <param name="dependencyObject">The DependencyObject to return the ErrorToolTip property value from</param> 
/// <returns>The value of the ErrorToolTip property.</returns> 
public static string GetErrorToolTip(DependencyObject dependencyObject) 
{ 
    return (string)dependencyObject.GetValue(ErrorToolTipProperty); 
} 

/// <summary> 
/// Sets the value of the ErrorToolTip property. 
/// </summary> 
/// <param name="dependencyObject">The DependencyObject to set the ErrorToolTip property value of</param> 
/// <param name="value">The value to be assigned to the ErrorToolTip property.</param> 
public static void SetErrorToolTip(DependencyObject dependencyObject, string value) 
{ 
    dependencyObject.SetValue(ErrorToolTipProperty, value); 
} 

/// <summary> 
/// If an Error Tooltip is supplied, sets the ToolTip to that value, otherwise, resets it back to MyToolTipProperty 
/// </summary> 
/// <param name="dependencyObject">The control with the tooltip</param> 
/// <param name="e">The DependencyPropertyChangedEventArgs object containing event specific information.</param> 
public static void OnErrorToolTipChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
{ 
    if (dependencyObject is TextBox) 
    { 
     var txtControl = dependencyObject as TextBox; 
     if (e.NewValue == null || e.NewValue.ToString() == string.Empty) 
     { 
      // No tooltip, reset to the original value 
      txtControl.ToolTip = (string)dependencyObject.GetValue(MyToolTipProperty); 
     } 
     else 
     { 
      // Use the error tooltip 
      txtControl.ToolTip = e.NewValue; 
     } 
    } 
} 

/// <summary> 
/// This should only be called when the value is first assigned to the control. 
/// </summary> 
/// <param name="dependencyObject">The Control</param> 
/// <param name="e">The DependencyPropertyChangedEventArgs object containing event 
/// specific information.</param> 
public static void OnMyToolTipChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
{ 
    // What type of control - I may be able to use a generic parent that supports Tooltips, but until I have time to figure that out, using this to generate a valid control.ToolTip reference. 
    if (dependencyObject is TextBox) 
    { 
     var txtControl = dependencyObject as TextBox; 
     if (e.OldValue != e.NewValue) 
     { 
      txtControl.ToolTip = e.NewValue; 
     } 
    } 
    else if (dependencyObject is ComboBox) 
    { 
     // Add code here for ComboBox and other tooltip controls (if we can't use a parent/interface reference instead.) 
    } 
} 

當然,還有在款式更等,但我離開了這一切,所以你剛剛要解決這個問題的代碼。

希望這可以幫助別人......

(如果你認爲你可以做的更好,去爲它的更多的想法越好)