提交 c10fc85f authored 作者: Mitch Capper's avatar Mitch Capper

Made NO_FS a bit more robust

Moved broker to have an actuall make call function so other things can place calls
Added Contact Search Box support, it is a bit hacky to say the least.....
上级 f2269751
...@@ -6,7 +6,8 @@ using System.Windows; ...@@ -6,7 +6,8 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Xml; using System.Xml;
using FreeSWITCH.Native; using FreeSWITCH.Native;
using FSClient.Controls;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
namespace FSClient { namespace FSClient {
...@@ -70,6 +71,8 @@ namespace FSClient { ...@@ -70,6 +71,8 @@ namespace FSClient {
try {//it would be better if this was in the init function but it seems some dll load errors won't be caught if it is. try {//it would be better if this was in the init function but it seems some dll load errors won't be caught if it is.
#if ! NO_FS #if ! NO_FS
fs_core_init(); fs_core_init();
#else
fs_inited = false;
#endif #endif
if (FreeswitchLoaded != null) if (FreeswitchLoaded != null)
FreeswitchLoaded(this, null); FreeswitchLoaded(this, null);
...@@ -82,14 +85,16 @@ namespace FSClient { ...@@ -82,14 +85,16 @@ namespace FSClient {
Environment.Exit(-1); Environment.Exit(-1);
} }
#if ! NO_FS
DelayedFunction.DelayedCall("SofiaProfileCheck", sofia.sofia_profile_check, 100); DelayedFunction.DelayedCall("SofiaProfileCheck", sofia.sofia_profile_check, 100);
#endif
} }
private void initContactManager() { private void initContactManager() {
contact_plugin_manager = new ContactPluginManager(); contact_plugin_manager = new ContactPluginManager();
} }
#region Text Input #region Text Input
...@@ -118,8 +123,10 @@ namespace FSClient { ...@@ -118,8 +123,10 @@ namespace FSClient {
if (Call.active_call != null && Call.active_call.state == Call.CALL_STATE.Answered) if (Call.active_call != null && Call.active_call.state == Call.CALL_STATE.Answered)
Call.active_call.send_dtmf(key.ToString()); Call.active_call.send_dtmf(key.ToString());
else { else {
#if ! NO_FS
PortAudio.PlayDTMF(key, null, true); PortAudio.PlayDTMF(key, null, true);
DelayedFunction.DelayedCall("PortAudioLastDigitHitStreamClose", close_streams, 5000); DelayedFunction.DelayedCall("PortAudioLastDigitHitStreamClose", close_streams, 5000);
#endif
} }
} }
private void close_streams() { private void close_streams() {
...@@ -219,6 +226,26 @@ namespace FSClient { ...@@ -219,6 +226,26 @@ namespace FSClient {
//OffHook = true; //OffHook = true;
//Utils.bgapi_exec("pa", "play tone_stream://%(10000,0,350,440);loops=20"); //Utils.bgapi_exec("pa", "play tone_stream://%(10000,0,350,440);loops=20");
} }
public void DialString(String str){
if (string.IsNullOrWhiteSpace(str))
return;
MainWindow.get_instance().RemoveFocus();
if (str.StartsWith("#") && str.Length > 2) {
String acct_num = str.Substring(1, 1);
str = str.Substring(2);
Account acct = (from a in Account.accounts where a.guid == acct_num select a).SingleOrDefault();
if (acct != null) {
acct.CreateCall(str);
return;
}
}
if (Account.default_account == null) {
MessageBox.Show("no default account, make sure you have added one or more accounts (right click in the account area to add) and they are enabled (checked)");
return;
}
Account.default_account.CreateCall(str);
}
public void TalkPressed() { public void TalkPressed() {
if (Call.active_call != null) { if (Call.active_call != null) {
if (Call.active_call.state == Call.CALL_STATE.Ringing && Call.active_call.is_outgoing == false) if (Call.active_call.state == Call.CALL_STATE.Ringing && Call.active_call.is_outgoing == false)
...@@ -228,22 +255,8 @@ namespace FSClient { ...@@ -228,22 +255,8 @@ namespace FSClient {
} else { } else {
if (String.IsNullOrEmpty(cur_dial_str)) if (String.IsNullOrEmpty(cur_dial_str))
DialTone(); DialTone();
else { else{
if (cur_dial_str.StartsWith("#") && cur_dial_str.Length > 2) { DialString(cur_dial_str);
String acct_num = cur_dial_str.Substring(1, 1);
cur_dial_str = cur_dial_str.Substring(2);
Account acct = (from a in Account.accounts where a.guid == acct_num select a).SingleOrDefault();
if (acct != null) {
acct.CreateCall(cur_dial_str);
cur_dial_str = "";
return;
}
}
if (Account.default_account == null) {
MessageBox.Show("no default account, make sure you have added one or more accounts (right click in the account area to add) and they are enabled (checked)");
return;
}
Account.default_account.CreateCall(cur_dial_str);
cur_dial_str = ""; cur_dial_str = "";
} }
} }
...@@ -548,12 +561,16 @@ namespace FSClient { ...@@ -548,12 +561,16 @@ namespace FSClient {
sofia.reload_config(mode); sofia.reload_config(mode);
} }
public static EventHandler<EventArgs> FreeswitchLoaded; public static EventHandler<EventArgs> FreeswitchLoaded;
public static EventHandler<FSEvent> NewEvent; public static EventHandler<FSEvent> NewEvent;
private void event_handler(FreeSWITCH.EventBinding.EventBindingArgs args) { private void event_handler(FreeSWITCH.EventBinding.EventBindingArgs args) {
if (BroadcastHandler == null) if (BroadcastHandler == null)
BroadcastHandler = new BroadcastEventDel(BroadcastEvent); BroadcastHandler = new BroadcastEventDel(BroadcastEvent);
Application.Current.Dispatcher.BeginInvoke(BroadcastHandler, new object[] { new FSEvent(args.EventObj) }); Application.Current.Dispatcher.BeginInvoke(BroadcastHandler, new object[] { new FSEvent(args.EventObj) });
}
public OurAutoCompleteBox GetContactSearchBox() {
return MainWindow.get_instance().GetContactSearchBox();
} }
private delegate void BroadcastEventDel(FSEvent evt); private delegate void BroadcastEventDel(FSEvent evt);
BroadcastEventDel BroadcastHandler; BroadcastEventDel BroadcastHandler;
...@@ -587,7 +604,7 @@ namespace FSClient { ...@@ -587,7 +604,7 @@ namespace FSClient {
private bool is_inited; private bool is_inited;
private bool fs_inited; private bool fs_inited;
private static IDisposable event_bind; private static IDisposable event_bind;
private void fs_core_init() { private void fs_core_init() {
fs_inited = true; fs_inited = true;
freeswitch.switch_core_set_globals(); freeswitch.switch_core_set_globals();
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
namespace FSClient.Controls {
public class OurAutoCompleteBox : AutoCompleteBox {
private TextBox the_textbox;
private void find_textbox(){
if (the_textbox != null)
return;
the_textbox = Template.FindName("Text", this) as TextBox;
}
public TextBox GetActualTextbox() {
find_textbox();
return the_textbox;
}
public bool TextBoxHasFocus(){
find_textbox();
if (the_textbox == null)
return false;
return the_textbox.IsFocused;
}
public void TextBoxFocus(){
find_textbox();
if (the_textbox != null)
the_textbox.Focus();
}
}
}
...@@ -68,6 +68,10 @@ ...@@ -68,6 +68,10 @@
<Reference Include="System.configuration" /> <Reference Include="System.configuration" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />
<Reference Include="System.Windows.Controls.Input.Toolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\WPF Toolkit\v3.5.50211.1\System.Windows.Controls.Input.Toolkit.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml" /> <Reference Include="System.Xaml" />
<Reference Include="System.Xml"> <Reference Include="System.Xml">
...@@ -91,6 +95,7 @@ ...@@ -91,6 +95,7 @@
<Compile Include="Account.cs" /> <Compile Include="Account.cs" />
<Compile Include="Broker.cs" /> <Compile Include="Broker.cs" />
<Compile Include="Call.cs" /> <Compile Include="Call.cs" />
<Compile Include="Controls\OurAutoCompleteBox.cs" />
<Compile Include="Controls\PhonePadButton.xaml.cs"> <Compile Include="Controls\PhonePadButton.xaml.cs">
<DependentUpon>PhonePadButton.xaml</DependentUpon> <DependentUpon>PhonePadButton.xaml</DependentUpon>
</Compile> </Compile>
......
...@@ -5,7 +5,9 @@ using System.ComponentModel; ...@@ -5,7 +5,9 @@ using System.ComponentModel;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using FSClient.Controls;
namespace FSClient { namespace FSClient {
public class ContactPluginManager : IDisposable { public class ContactPluginManager : IDisposable {
private bool IsTypeOf(Type to_check, Type of) { private bool IsTypeOf(Type to_check, Type of) {
...@@ -15,6 +17,9 @@ namespace FSClient { ...@@ -15,6 +17,9 @@ namespace FSClient {
return true; return true;
return IsTypeOf(to_check.BaseType, of); return IsTypeOf(to_check.BaseType, of);
} }
public static IEnumerable<MenuItem> ContactMenuItems { get; set; }
private List<IContactPlugin> plugins = new List<IContactPlugin>(); private List<IContactPlugin> plugins = new List<IContactPlugin>();
public void RegisterPlugin(IContactPlugin plugin) { public void RegisterPlugin(IContactPlugin plugin) {
if (plugins.Count > 0) if (plugins.Count > 0)
...@@ -22,13 +27,24 @@ namespace FSClient { ...@@ -22,13 +27,24 @@ namespace FSClient {
try { try {
plugins.Add(plugin); plugins.Add(plugin);
plugin.Initialize(); plugin.Initialize();
Application.Current.Dispatcher.BeginInvoke((Action)ContactInit);
} catch (Exception e) { } catch (Exception e) {
HandleError(plugin, e); HandleError(plugin, e);
} }
} }
private void ContactInit(){
IContactPlugin plugin = plugins[0];
ContactMenuItems = plugin.ContactRightClickMenu();
OurAutoCompleteBox box = Broker.get_instance().GetContactSearchBox();
if (!plugin.HandleSearchBox(box))
box.Visibility = Visibility.Collapsed;
}
private void HandleError(IContactPlugin plugin, Exception e) { private void HandleError(IContactPlugin plugin, Exception e) {
Utils.PluginLog("Contact Plugin Manager", "Plugin \"" + plugin.ProviderName() + "\" had an error Due to: " + e.Message); Utils.PluginLog("Contact Plugin Manager", "Plugin \"" + plugin.ProviderName() + "\" had an error Due to: " + e.Message);
}
}
public ContactPluginManager() { public ContactPluginManager() {
...@@ -62,17 +78,17 @@ namespace FSClient { ...@@ -62,17 +78,17 @@ namespace FSClient {
Utils.PluginLog("Contact Plugin Manager", "Error creating contact plugin from dll \"" + dll + "\" of: " + e.Message); Utils.PluginLog("Contact Plugin Manager", "Error creating contact plugin from dll \"" + dll + "\" of: " + e.Message);
} }
} }
Call.calls.CollectionChanged += calls_CollectionChanged; Call.calls.CollectionChanged += calls_CollectionChanged;
Call.CallRightClickMenuShowing += calls_RightClickMenuShowing; Call.CallRightClickMenuShowing += calls_RightClickMenuShowing;
} }
private void calls_RightClickMenuShowing(object sender, Call.CallRightClickEventArgs e){ private void calls_RightClickMenuShowing(object sender, Call.CallRightClickEventArgs e){
if (plugins.Count == 0) if (plugins.Count == 0)
return; return;
plugins[0].CallRightClickMenu(e.call, e.menu); plugins[0].CallRightClickMenu(e.call, e.menu);
} }
private void calls_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { //We want to background resolve things incase a plugin does something that takes awhile private void calls_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { //We want to background resolve things incase a plugin does something that takes awhile
if (e.NewItems == null || plugins.Count != 1) if (e.NewItems == null || plugins.Count != 1)
return; return;
...@@ -140,11 +156,13 @@ namespace FSClient { ...@@ -140,11 +156,13 @@ namespace FSClient {
public abstract class IContactPlugin { public abstract class IContactPlugin {
public delegate void NumberResolved(String DisplayName); public delegate void NumberResolved(String DisplayName);
public abstract void ResolveNumber(String number, NumberResolved on_resolved); public abstract void ResolveNumber(String number, NumberResolved on_resolved);
public abstract void CallRightClickMenu(Call call, ContextMenu menu); public abstract void CallRightClickMenu(Call call, ContextMenu menu);
public abstract IEnumerable<MenuItem> ContactRightClickMenu();
public abstract void Initialize(); public abstract void Initialize();
public abstract void Terminate(); public abstract void Terminate();
public abstract string ProviderName(); public abstract string ProviderName();
public abstract bool HandleSearchBox(OurAutoCompleteBox box);
} }
} }
<Window <Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ours="clr-namespace:FSClient.Controls" xmlns:ours="clr-namespace:FSClient.Controls" xmlns:local="clr-namespace:FSClient" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit" mc:Ignorable="d" x:Class="FSClient.MainWindow"
xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit" xmlns:local="clr-namespace:FSClient" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="FSClient.MainWindow"
Title="FSClient" Height="319" Width="666" WindowStyle="SingleBorderWindow" ResizeMode="CanMinimize" Closing="Window_Closing" Icon="phone.ico"> Title="FSClient" Height="319" Width="666" WindowStyle="SingleBorderWindow" ResizeMode="CanMinimize" Closing="Window_Closing" Icon="phone.ico">
<Window.Resources> <Window.Resources>
<local:DurationTimeConverter x:Key="DurationTimeConverter"/> <local:DurationTimeConverter x:Key="DurationTimeConverter"/>
...@@ -174,15 +172,27 @@ ...@@ -174,15 +172,27 @@
</StackPanel> </StackPanel>
</Border> </Border>
<Button Content="Options" HorizontalAlignment="Left" x:Name="btnOptions" Width="75" Click="btnOptions_Click" Style="{DynamicResource GlassButtonStyle}" Height="20" Canvas.Left="349" Canvas.Top="266" d:LayoutOverrides="VerticalAlignment" /> <Button Content="Options" HorizontalAlignment="Left" x:Name="btnOptions" Width="50" Click="btnOptions_Click" Style="{DynamicResource GlassButtonStyle}" Height="20" Canvas.Left="374" Canvas.Top="266" d:LayoutOverrides="VerticalAlignment" />
</Canvas> </Canvas>
<Button Canvas.Left="283" Canvas.Top="21" Content="Send To Voicemail" FontWeight="Bold" Foreground="#FFF5E200" Height="20" Name="btnSendVoicemail" Style="{DynamicResource GlassButtonStyle}" Width="120" Visibility="Hidden" Click="btnSendVoicemail_Click" /> <Button Canvas.Left="283" Canvas.Top="21" Content="Send To Voicemail" FontWeight="Bold" Foreground="#FFF5E200" Height="20" Name="btnSendVoicemail" Style="{DynamicResource GlassButtonStyle}" Width="120" Visibility="Hidden" Click="btnSendVoicemail_Click" />
<ours:OurAutoCompleteBox Canvas.Left="435" Text="Contact Search" Canvas.Top="265" Height="22" Width="164.553" Opacity="0.8" x:Name="txtSearchBox" FilterMode="Contains" GotKeyboardFocus="txtSearchBox_GotKeyboardFocus" LostKeyboardFocus="txtSearchBox_LostKeyboardFocus" DropDownClosing="txtSearchBox_DropDownClosing">
<ours:OurAutoCompleteBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.ContextMenu>
<ContextMenu x:Name="contactSearchConextMenu" ItemsSource="{Binding Path=(local:ContactPluginManager.ContactMenuItems)}" IsEnabled="true" Closed="contactSearchConextMenu_Closed" Loaded="contactSearchConextMenu_Loaded" />
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ours:OurAutoCompleteBox.ItemTemplate>
</ours:OurAutoCompleteBox>
<Control <Control
x:Name="busyAnimation" x:Name="busyAnimation"
Style="{StaticResource BusyAnimationStyle}" Style="{StaticResource BusyAnimationStyle}"
Width="{Binding Path=ActualWidth, ElementName=mainControl}" Width="{Binding Path=ActualWidth, ElementName=mainControl}"
Height="{Binding Path=ActualHeight, ElementName=mainControl}" Height="{Binding Path=ActualHeight, ElementName=mainControl}" d:IsHidden="True"
/> />
</Canvas> </Canvas>
</Window> </Window>
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input;
using FSClient.Controls;
namespace FSClient namespace FSClient
{ {
...@@ -8,9 +12,9 @@ namespace FSClient ...@@ -8,9 +12,9 @@ namespace FSClient
{ {
protected abstract void _TryResolveNewNumber(string number, NumberResolved on_resolved); protected abstract void _TryResolveNewNumber(string number, NumberResolved on_resolved);
protected abstract void LoadDatabase(ref Dictionary<string, string> number_to_alias_db); protected abstract void LoadDatabase(ref Dictionary<string, string> number_to_alias_db);
protected abstract void UpdateDatabase(string number, string alias); protected abstract void UpdateDatabase(string number, string alias);
protected virtual void ModifyRightClickMenu(Call call, ContextMenu menu) protected virtual void ModifyRightClickMenu(Call call, ContextMenu menu)
{ {
return; return;
...@@ -30,26 +34,65 @@ namespace FSClient ...@@ -30,26 +34,65 @@ namespace FSClient
return ""; return "";
} }
protected Dictionary<string, string> number_to_alias = new Dictionary<string, string>(); protected Dictionary<string, string> number_to_alias = new Dictionary<string, string>();
public override void CallRightClickMenu(Call call, ContextMenu menu) { public override void CallRightClickMenu(Call call, ContextMenu menu) {
MenuItem item = new MenuItem(); MenuItem item = new MenuItem();
item.Click += item_Click; item.Click += item_Click;
item.Header = "Edit Contact"; item.Header = "Edit Contact";
menu.Items.Add(item); menu.Items.Add(item);
ModifyRightClickMenu(call, menu); ModifyRightClickMenu(call, menu);
} }
protected void item_Click(object sender, System.Windows.RoutedEventArgs e) public override IEnumerable<MenuItem> ContactRightClickMenu(){
List<MenuItem> items = new List<MenuItem>();
MenuItem item = new MenuItem();
item.Click += item_Click;
item.Header = "Edit Contact";
items.Add(item);
item = new MenuItem();
item.Click +=contact_call_click;
item.Header = "Call";
items.Add(item);
return items;
}
private void contact_call_click(object sender, RoutedEventArgs e){
MenuItem item = sender as MenuItem;
if (item == null)
return;
SearchAutoCompleteEntry entry = item.DataContext as SearchAutoCompleteEntry ?? search_box.SelectedItem as SearchAutoCompleteEntry;
if (entry == null)
return;
Broker.get_instance().DialString(entry.number);
}
protected void item_Click(object sender, RoutedEventArgs e)
{ {
MenuItem item = sender as MenuItem; MenuItem item = sender as MenuItem;
if (item == null) if (item == null)
return; return;
String number;
String default_edit_value;
Call c = item.DataContext as Call; Call c = item.DataContext as Call;
if (c == null) if (c != null){
return; number = c.other_party_number;
String number = NormalizeNumber(c.other_party_number); default_edit_value = DefaultEditValue(c);
String alias = InputBox.GetInput("Editing Contact", "Edit alias for number: " + number, DefaultEditValue(c)); }
else{
SearchAutoCompleteEntry entry = item.DataContext as SearchAutoCompleteEntry ?? search_box.SelectedItem as SearchAutoCompleteEntry;
if (entry == null)
return;
number = entry.number;
default_edit_value = entry.alias;
}
String orig_number = number;
number = NormalizeNumber(number);
String alias = InputBox.GetInput("Editing Contact", "Edit alias for number: " + number, default_edit_value);
alias = IsValidAlias(alias); alias = IsValidAlias(alias);
if (alias == null) if (alias == null)
return; return;
...@@ -58,11 +101,12 @@ namespace FSClient ...@@ -58,11 +101,12 @@ namespace FSClient
foreach (Call call in Call.calls) foreach (Call call in Call.calls)
{ {
if (c.other_party_number == call.other_party_number) if (orig_number == call.other_party_number || number == call.other_party_number)
c.other_party_name = alias; call.other_party_name = alias;
} }
UpdateDatabase(number, alias); UpdateDatabase(number, alias);
refresh_search_box();
} }
public override void ResolveNumber(string number, NumberResolved on_resolved) public override void ResolveNumber(string number, NumberResolved on_resolved)
{ {
...@@ -78,8 +122,69 @@ namespace FSClient ...@@ -78,8 +122,69 @@ namespace FSClient
public override void Initialize() public override void Initialize()
{ {
LoadDatabase(ref number_to_alias); LoadDatabase(ref number_to_alias);
refresh_search_box();
}
protected void refresh_search_box(){
if (search_box == null)
return;
search_box.ItemsSource = from c in number_to_alias select new SearchAutoCompleteEntry(c.Key,c.Value);
}
protected class SearchAutoCompleteEntry{
public string number;
public string alias;
public string display_name;
public SearchAutoCompleteEntry(String number, String alias){
this.number = number;
this.alias = alias;
if (String.IsNullOrWhiteSpace(alias) || number == alias)
display_name = number;
else
display_name = alias + " - " + number;
}
public override string ToString(){
return display_name;
}
}
protected void search_box_PreviewKeyUp(object sender, KeyEventArgs e){
if (e.Key == Key.Enter){
call_current_contact();
}
}
protected OurAutoCompleteBox search_box;
private TextBox real_search_box;
public override bool HandleSearchBox(OurAutoCompleteBox box) {
search_box = box;
real_search_box = search_box.GetActualTextbox();
real_search_box.ContextMenu = new ContextMenu();
real_search_box.ContextMenuOpening += search_box_ContextMenuOpening;
foreach (MenuItem item in ContactRightClickMenu()){
real_search_box.ContextMenu.Items.Add(item);
}
search_box.PreviewKeyUp += search_box_PreviewKeyUp;
search_box.MouseDoubleClick += search_box_MouseDoubleClick;
if (number_to_alias.Count > 0)
refresh_search_box();
return true;
}
protected void call_current_contact(){
SearchAutoCompleteEntry entry = search_box.SelectedItem as SearchAutoCompleteEntry;
if (entry != null)
Broker.get_instance().DialString(entry.number);
}
void search_box_MouseDoubleClick(object sender, MouseButtonEventArgs e){
call_current_contact();
} }
void search_box_ContextMenuOpening(object sender, ContextMenuEventArgs e){
if (search_box.SelectedItem == null)
real_search_box.ContextMenu.Visibility = Visibility.Hidden;
else
real_search_box.ContextMenu.Visibility = Visibility.Visible;
}
} }
} }
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论