How can I make the control can not be click while overlying? - wpf

I make an easy demo by WPF, here is the XAML:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid PreviewMouseLeftButtonDown="Grid_PreviewMouseLeftButtonDown" Background="White">
<Border Height="100" Width="100" Background="Red" PreviewMouseLeftButtonDown="Border_PreviewMouseLeftButtonDown"></Border>
</Grid>
</Window>
And here is the code-behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Border_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Border");
}
private void Grid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Grid");
}
}
}
I wanna do that if I press the border, it only activates the "Border" message box but not with the "Grid" message box also.
How can I do it? Would you please help me?
Thank you.

you can replace PreviewMouseLeftButtonDown with MouseDown.

Related

Remove an attribute from xaml using c# - WPF

This question is related to removing an attribute in xaml.
In the below code, I have a Span. During an event, I add a back ground to this Span. During another event, I need to remove it. Please let me know, if there is a way to remove the background attribute I set to Span.
My Xaml looks like this.
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication4"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
</Grid.RowDefinitions>
<RichTextBox x:Name="rtb">
<FlowDocument>
<Paragraph>
<Span x:Name="def" Tag="default">
<Run x:Name="deg">Some Text</Run>
</Span>
</Paragraph>
</FlowDocument>
</RichTextBox>
<TextBox x:Name="tx" Grid.Row="1" TextWrapping="Wrap"/>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Content="s" Click="Button_Click"/>
<Button Content="bg-Add" Grid.Column="1" Click="Button_Click"/>
<Button Content="bg-Remove" Grid.Column="2" Click="Button_Click"/>
</Grid>
</Grid>
</Window>
My code looks like this.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows. Shapes;
namespace WpfApplication4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if ((sender as Button).Content.ToString() == "s")
{
tx.Text = XamlWriter.Save(def);
}
else if ((sender as Button).Content.ToString() == "bg-Add")
{
def.Background = new SolidColorBrush(Colors.Blue);
}
else if ((sender as Button).Content.ToString() == "bg-Remove")
{
//Need to remove the set back color so that I get the default back
}
}
}
}
I am able to find an answer myself.
def.ClearValue(Span.BackgroundProperty);
is going to remove that attribute for me.
You can override ShouldSerializeProperty
public class CustomizedSpan : Span
{
public bool IsRemoveBackGround;
protected override bool ShouldSerializeProperty(DependencyProperty dp)
{
if (dp == Span.BackgroundProperty && IsRemoveBackGround)
{
return false;
}
else
{
return base.ShouldSerializeProperty(dp);
}
}
}

Avoid dropdown selection change event during view load

Grid contains dropdown control. I want to avoid selection change event during view load. What is the best way to achieve that?
Well i don't know what dropdown control is in WPF
I have tried with combobox and SelectionChanged event in not firing at form load
Here's my code
<Window x:Class="Q6.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Q6"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ComboBox SelectionChanged="ComboBox_SelectionChanged"
Height="30" Width="100">
<ComboBoxItem>Alpha</ComboBoxItem>
<ComboBoxItem>Beta</ComboBoxItem>
<ComboBoxItem>Gamma</ComboBoxItem>
</ComboBox>
</Grid>
</Window>
And the code-behind :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Q6
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//Not firing at load time
}
}
}

Custom ItemControl for ListBox

I want to add new DependencyProperty to ListBoxItem class which used in ListBox control. I need to add IsEditing property. When user will does long click on my ListBoxItem I will change it IsEditing property to True and then in Trigger of this property will be style changing. Actually the idea to change TextBlock to TextBox in style.
I hope my explanation is clear. Does it make any sense, or there is exist more simple way?
Thanks
See the XAML below - A child of DataTemplate is your item's template. You can use built-in WPF elements like Grid, Canvas etc. or your own user/custom control. You can create EditableItem control and use it to handle long mouse clicks etc.
This is not the most elegant way of doing this, but probably the simplest one. The more advanced approach would involve the usage of attached behaviors, which elliminates need for custom/user controls. Also, look at VisualStateManager class, it'll simplify switching between different 'modes' of your editable item (that's what I'd use for it anyway).
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox x:Name="l">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Height="30" Background="Green" Width="100">
<TextBlock Text="{Binding}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += (o, e) =>
{
this.l.ItemsSource = Enumerable.Range(1, 3);
};
}
}
}

MP3 does not trigger the Storyboard.Completed event

I am trying to use the Storyboard's Completed event to indicate when an audio file has finished playing.
However, it seems .Net behaves differently when playing mp3 and wav files, and the event is triggered only for WAV.
Here is a XAML and code that demonstrate the problem:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
x:Name="mainWind">
<Window.Resources>
<Storyboard x:Key="mp3StoryBoard" Completed="Storyboard_Completed">
<MediaTimeline Source="001.mp3" Storyboard.TargetName="mediaEl" >
</MediaTimeline>
</Storyboard>
<Storyboard x:Key="wavStoryBoard" Completed="Storyboard_Completed">
<MediaTimeline Source="001.wav" Storyboard.TargetName="mediaEl" >
</MediaTimeline>
</Storyboard>
</Window.Resources>
<Grid>
<MediaElement x:Name="mediaEl" Height="120" HorizontalAlignment="Left" Margin="120,94,0,0" VerticalAlignment="Top" Width="160" />
<Button Content="Play MP3" Height="23" HorizontalAlignment="Left" Margin="148,260,0,0" Name="btnMP3" VerticalAlignment="Top" Width="75" Click="button1_Click" />
<Button Content="Play WAV" Height="23" HorizontalAlignment="Left" Margin="267,260,0,0" Name="btnWAV" VerticalAlignment="Top" Width="75" Click="btnWAV_Click" />
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Storyboard sb = (Storyboard)this.mainWind.Resources["mp3StoryBoard"];
sb.Begin();
}
private void Storyboard_Completed(object sender, EventArgs e)
{
MessageBox.Show(" Storyboard finished");
}
private void btnWAV_Click(object sender, RoutedEventArgs e)
{
Storyboard sb = (Storyboard)this.mainWind.Resources["wavStoryBoard"];
sb.Begin();
}
}
}
Will be glad if anyone has an idea for the reason for that and how to overcome it.
You don't have an attached event handler.
You need a
sb.Completed +=Storyboard_Completed;
before
The WPF MediaKit includes a MediaElement replacement, which may work better with mp3 files.

silverlight binding combobox in nested controls

I have 2 user controls one named Filters and one named FilterItem
Filter looks like this:
<UserControl xmlns:my="clr-namespace:AttorneyDashboard.Views.UserControls" x:Class="AttorneyDashboard.Views.UserControls.Filters"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:helpers="clr-namespace:AttorneyDashboard.Helpers"
mc:Ignorable="d"
d:DesignHeight="150" d:DesignWidth="590" x:Name="FiltersRoot">
<Grid>
<ListBox x:Name="myListBox" ItemsSource="{Binding Path=FilterItems, ElementName=FiltersRoot}" >
<ListBox.ItemTemplate>
<DataTemplate>
<my:FilterItem ColumnsList="{Binding Path=Columns_, ElementName=FiltersRoot}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
Code Behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
using System.Collections.ObjectModel;
using System.Diagnostics;
using AttorneyDashboard.Helpers;
namespace AttorneyDashboard.Views.UserControls
{
public class MyItems
{
public string Header { get; set; }
}
public partial class Filters : UserControl
{
public Filters()
{
InitializeComponent();
}
private DependencyProperty FilterItemsProperty = DependencyProperty.Register("FilterItems", typeof(ObservableCollection<FilterDescriptor>), typeof(Filters), new PropertyMetadata(null, new PropertyChangedCallback(OnChangeFilterItems)));
public ObservableCollection<FilterDescriptor> FilterItems
{
get
{
return (ObservableCollection<FilterDescriptor>)GetValue(FilterItemsProperty);
}
set
{
SetValue(FilterItemsProperty, value);
}
}
public static void OnChangeFilterItems(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
public List<MyItems> Columns_
{
get
{
List<MyItems> list = new List<MyItems>();
list.Add(new MyItems() { Header = "test1" });
list.Add(new MyItems() { Header = "test2" });
list.Add(new MyItems() { Header = "test3" });
return list;
}
}
}
}
FilterItems looks like this
<UserControl x:Class="AttorneyDashboard.Views.UserControls.FilterItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="23" d:DesignWidth="590" xmlns:my="clr-namespace:AttorneyDashboard.Helpers" x:Name="FilterItemRoot">
<StackPanel Orientation="Horizontal">
<ComboBox Height="23" HorizontalAlignment="Left" Name="FieldName" VerticalAlignment="Top" Width="120" Margin="5,0,0,0" ItemsSource="{Binding Path=ColumnsList, ElementName=FilterItemRoot}" SelectedItem="{Binding PropertyPath, Mode=TwoWay}" DisplayMemberPath="Header"/>
</StackPanel>
</UserControl>
Code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using AttorneyDashboard.Helpers;
using System.Windows.Data;
namespace AttorneyDashboard.Views.UserControls
{
public partial class FilterItem : UserControl
{
public FilterItem()
{
InitializeComponent();
}
private DependencyProperty ColumnsListProperty = DependencyProperty.Register("ColumnsList", typeof(List<MyItems>), typeof(FilterItem), new PropertyMetadata(null, new PropertyChangedCallback(OnChangeColumns)));
public List<MyItems> ColumnsList
{
get
{
return (List<MyItems>)GetValue(ColumnsListProperty);
}
set
{
SetValue(ColumnsListProperty, value);
}
}
public static void OnChangeColumns(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
}
}
The number of FilterItems is ok (this means that FilterItems binding works ok), but only the Combobox of the last FilterItem is populated...
And I do not know what exactly is wrong...
Update:
I found why but I stll do not know a solution...
It seams that the content of FilterItem is binded before his properties are..
So the combobox in FilterItem is binded before the Columns property is binded...
Your code in FilterItem
private DependencyProperty ColumnsListProperty = DependencyProperty
.Register("ColumnsList", typeof(List<MyItems>), typeof(FilterItem),
new PropertyMetadata(null, new PropertyChangedCallback(OnChangeColumns)));
Please, make it static:
private **static** DependencyProperty ColumnsListProperty = DependencyProperty
.Register("ColumnsList", typeof(List<MyItems>), typeof(FilterItem),
new PropertyMetadata(null, new PropertyChangedCallback(OnChangeColumns)));
Thats it.
P.S. : in Filters make dependency property static too, generally do it anywhere :)
You have placed a x:Name attribute directly on your UserControl elements. Don't do that. Use this pattern instead:-
<UserControl x:Class="AttorneyDashboard.Views.UserControls.FilterItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="23" d:DesignWidth="590" xmlns:my="clr-namespace:AttorneyDashboard.Helpers" >
<StackPanel Orientation="Horizontal" x:Name="LayoutRoot">
<ComboBox Height="23" HorizontalAlignment="Left" Name="FieldName" VerticalAlignment="Top" Width="120" Margin="5,0,0,0" ItemsSource="{Binding Path=Parent.ColumnsList, ElementName=LayoutRoot}" SelectedItem="{Binding PropertyPath, Mode=TwoWay}" DisplayMemberPath="Header"/>
</StackPanel>
</UserControl>
You are not in control of name assigned to the user control, that belongs in the scope of the Xaml the uses your UserControl. If your code internally requires that the containing UserControl have a specific name then things are likely to break.

Resources