I want to create a Tab Control which can hold for multiple User Controls.
<TabControl Padding="0">
<TabItem Header="{x:Static p:Resources.Scheduler}"
Visibility="{Binding ShellService.IsSchedulerEnabled,
Converter={StaticResource BoolToVisibilityConverter}}">
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<Trigger Property="IsVisible" Value="True">
<Setter Property="Content"
Value="{Binding ShellService.LazySchedulerView.Value}"/>
</Trigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</TabItem>
</TabControl>
The xaml is only for 1 tab item, which control by ShellService.IsSchedulerEnabled and the content is ShellService.LazySchedulerView.Value.
My problem here is that if I want to create a new TabItem, I have to create a new TabItem tag in the xaml.
How can I create a dynamic tab control to hold more than 1 tab item without specifying 'Value' in ContentControl.
public interface IShellService : INotifyPropertyChanged
{
object ShellView { get; }
bool IsSchedulerEnabled { get; set; }
Lazy<object> LazySchedulerView { get; set; }
}
[Export(typeof(IShellService)), Export]
internal class ShellService : Model, IShellService
{
private object _shellView;
private bool _isSchedulerEnabled;
private Lazy<object> _lazySchedulerView;
public object ShellView
{
get { return _shellView; }
set { SetProperty(ref _shellView, value); }
}
public bool IsSchedulerEnabled
{
get { return _isSchedulerEnabled; }
set { SetProperty(ref _isSchedulerEnabled, value); }
}
public Lazy<object> LazySchedulerView
{
get { return _lazySchedulerView; }
set { SetProperty(ref _lazySchedulerView, value); }
}
}
You can use Style for this TabItem. I created some example for you. You should change Bindings to your own. And you should create ObservableCollection of ShellServices and bind it to the TabControl. I hope this helps.
<TabControl ItemsSource="{Binding Objects}">
<TabControl.Resources>
<Style TargetType="TabItem" x:Key="{x:Type TabItem}">
<Setter Property="Header" Value="{Binding Header}"></Setter>
<Style.Triggers>
<Trigger Property="IsVisible" Value="True">
<Setter Property="Content" Value="{Binding Text}"/>
</Trigger>
</Style.Triggers>
</Style>
</TabControl.Resources>
</TabControl>
Update
ViewModel Sample
public class OwnObject : ViewModelBase
{
private string _text;
public string Text
{
get { return _text; }
set { _text = value; NotifyPropertyChanged( "Text" ); }
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
protected void NotifyPropertyChanged( String info )
{
if ( PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( info ) );
}
}
}
I bound these objects to TabControl.
private ObservableCollection<OwnObject> _objects = new ObservableCollection<OwnObject>();
public ObservableCollection<OwnObject> Objects
{
get { return _objects; }
set { _objects = value; NotifyPropertyChanged( "Objects" ); }
}
Related
Context :
I have a treeview with a separate details view injecting by PRISM library when I click on one of my treeviewitem (and I can update all properties of my item with it). All my items have a Enabled property.
Problem :
When I update programmatically my viewmodels property, my object is updated. If I click on an other treeviewitem and come back to the first one, I see the property was updated.
All the updates are good when I enable/disable the item using my details view (the foreground is going grey and the property is change)
But in my case, when I try to update it by a command triggered by a contextMenu it doesn't trigger the view and all the updates... but my viewmodel property is updated...
What am I going wrong ?
I am using ObservableCollection in my treeview, maybe I need to change the type of my collection ?
I have my BaseViewModel who implements NotifyPropertyChanged
public abstract class NotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(Expression<Func<object>> propertyExpression)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(GetPropertyName(propertyExpression)));
}
private string GetPropertyName(Expression<Func<object>> propertyExpression)
{
var unaryExpression = propertyExpression.Body as UnaryExpression;
var memberExpression = unaryExpression == null ? (MemberExpression)propertyExpression.Body : (MemberExpression)unaryExpression.Operand;
var propertyName = memberExpression.Member.Name;
return propertyName;
}
}
So I call the property change method, but Why my view is not updating then ?
[DefaultValue(true)]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public bool Enabled
{
get
{
return Model.Enabled;
}
set
{
if (value != Model.Enabled)
{
Model.Enabled = value;
OnPropertyChanged(() => Model.Enabled);
}
}
}
Here is the code of my view (for the command)
<MenuItem Header="Enable/Disable this equipment" Command="{Binding PlacementTarget.Tag.DataContext.ToogleEquipmentCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"
CommandParameter="{Binding}" InputGestureText="CTRL+D"/>
And here is the code of my view (Hierarchical data template from my treeview)
<!-- ModuleItems > IP / Name -->
<HierarchicalDataTemplate DataType="{x:Type siemens:ModuleItemSiemensViewModel}" >
<StackPanel Orientation="Horizontal">
<TextBlock Name="ItemIp"
Text="{Binding Path=Ip}" ContextMenu="{StaticResource ContextMenuEquipment}" Tag="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Enabled}" Value="False">
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
<DataTrigger Binding="{Binding Enabled}" Value="True">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text=" / " ContextMenu="{StaticResource ContextMenuEquipment}" Tag="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Enabled}" Value="False">
<Setter Property="Background" Value="LightGray"/>
</DataTrigger>
<DataTrigger Binding="{Binding Enabled}" Value="True">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Name="ItemName" ContextMenu="{StaticResource ContextMenuEquipment}" Tag="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"
Text="{Binding Path=Name}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Enabled}" Value="False">
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
<DataTrigger Binding="{Binding Enabled}" Value="True">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
EDIT :
Here is the code from my viewmodel and models :
My real problem is when I update an Item (with my property enabled) it update the item, but my list (ModuleItems) is not updated, what I need to do to correctly implement MVVM and to make my fields automatically updated ?
public class ModuleParamSiemensViewModel : ModuleParamBaseViewModel
{
#region Attributes
private ObservableCollection<ModuleItemSiemensViewModel> _moduleItems;
private ModuleParamSiemens _model;
private string _moduleType;
#endregion
#region Constructor
public ModuleParamSiemensViewModel(ModuleParamSiemens moduleParam) : base(moduleParam)
{
this.Model = moduleParam;
this.ModuleType = "Siemens";
ModuleItems = new ObservableCollection<ModuleItemSiemensViewModel>();
Initialize();
}
#endregion
#region Properties
public new ModuleParamSiemens Model
{
get
{
return _model;
}
set
{
if (value != _model)
{
_model = value;
OnPropertyChanged(() => Model);
}
}
}
public new ObservableCollection<ModuleItemSiemensViewModel> ModuleItems
{
get
{
return _moduleItems;
}
set
{
this._moduleItems = value;
OnPropertyChanged(() => ModuleItems);
}
}
public override string ModuleType
{
get
{
return _moduleType;
}
set
{
this._moduleType = value;
OnPropertyChanged(() => ModuleType);
}
}
#endregion
#region Public Methods
public void Initialize()
{
foreach (ModuleItemSiemens item in this.Model.ModuleItems)
{
Add(new ModuleItemSiemensViewModel(item));
}
}
public void Add(ModuleItemSiemensViewModel item)
{
ModuleItems.Add(item);
}
#endregion
}
Model :
public class ModuleParamSiemens : ModuleParam
{
public new ObservableCollection<ModuleItemSiemens> ModuleItems { get; set; }
public ModuleParamSiemens()
{
ModuleItems = new ObservableCollection<ModuleItemSiemens>();
}
}
EDIT 2 :
Add ItemSiemensViewModel
public class ItemSiemensViewModel : ItemBaseViewModel
{
#region Attributes
private ItemSiemens _model;
#endregion
#region Constructor
public ItemSiemensViewModel(ItemSiemens item)
{
this.Model = item;
}
#endregion
#region Properties
public new ItemSiemens Model
{
get
{
return _model;
}
set
{
if (value != _model)
{
_model = value;
OnPropertyChanged(() => Model);
}
}
}
public new OPCInfo Opc
{
get
{
return Model.Opc;
}
set
{
if (value != Model.Opc)
{
Model.Opc = value;
OnPropertyChanged(() => Model.Opc);
}
}
}
public ProtocolInfoSiemens Protocol
{
get
{
return Model.Protocol;
}
set
{
if (value != Model.Protocol)
{
Model.Protocol = value;
OnPropertyChanged(() => Model.Protocol);
}
}
}
#endregion
#region Public Methods
#endregion
}
ItemSiemens :
public class ItemSiemens : Item
{
public ProtocolInfoSiemens Protocol { get; set; }
}
ItemBaseViewModel
public abstract class ItemBaseViewModel : BaseViewModel
{
public OPCInfoBaseViewModel Opc { get; set; }
public ItemBaseViewModel()
{
}
}
Item
public abstract class Item
{
public OPCInfo Opc { get; set; }
}
I have found the answer.
My bindings are correct (or at least it works)
The problem is that I used ObservableCollection collection and when an item is update in this collection it's not even fire an event to say that something has changed (it does for adding and removing items)
So I have implemented my own ItemsChangeObservableCollection (you can look this answer : https://stackoverflow.com/a/33866549/8237280)
And now all my problems in all my app are solved !
You are sending INotifyPropertyChanged on your ModuleItemSiemensViewModel for the property Model.Enabled. This does not make much sense, as nobody is listening on the VM (ModuleItemSiemensViewModel) for this change. The INPC interface does not allow such a kind of update. Every control listens on the same object that it's binding a property. That means you can only send PropertyChanged for properties that are in the same class/instance the interface is declared.
You have to move the NotifyPropertyChanged to the "Model" instance and call it there like this:
[DefaultValue(true)]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public bool Enabled
{
get
{
return Model.Enabled;
}
set
{
if (value != Model.Enabled)
{
Model.Enabled = value;
Model.OnPropertyChanged(() => Enabled);
}
}
}
I have a ListBox with a GroupStyle that contains another ListBox.
Now I want to filter the Items of the nested ListBox depending on the group name of the parent ListBox.
In the code below I tried to chain the GroupItem.Name.Name property to the GroupName property of the ViewModel of the nested ListBox, but this didn't work out so well.
Essentially the GroupNameIn Property is filled by the GroupItems' name(the TextBlock Text) and then sets the GroupNameOut Property to the same value in the PropertyChangedCallback. But the problem is that the GroupName Property of the NestedItemsViewModel to which GroupNameOut is bound to doesn't update.
Are there some mistakes in my approach or is there even a simpler/better way to achieve this behavior?
I would be very grateful if someone could point me in the right direction.
GroupStyle of the parent ListBox:
<Style x:Key="MyListBoxGroupStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<StackPanel Name="container" Width="Auto" Orientation="Vertical">
<TextBlock Name="groupNameTextBlock" Text="{Binding Path=Name.Name}"/>
<ItemsPresenter/>
<MyNestedListBox
DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}, Path=NestedItemsDataContext}"
ItemsSource="{Binding NestedItems}"
GroupNameIn="{Binding ElementName=groupNameTextBlock, Path=Text}"
GroupNameOut="{Binding Path=GroupName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The nested ListBox:
public class MyNestedListBox : ListBox
{
static MyNestedListBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyNestedListBox), new FrameworkPropertyMetadata(typeof(MyNestedListBox)));
}
public string GroupNameIn
{
get { return (string)GetValue(GroupNameInProperty); }
set { SetValue(GroupNameInProperty, value); }
}
public string GroupNameOut
{
get { return (string)GetValue(GroupNameOutProperty); }
set { SetValue(GroupNameOutProperty, value); }
}
// DepenencyProperties
public static readonly DependencyProperty GroupNameInProperty =
DependencyProperty.Register("GroupNameIn", typeof(string), typeof(MyNestedListBox), new UIPropertyMetadata(null) { PropertyChangedCallback = (obj, target) =>
{
obj.SetValue(GroupNameOutProperty, target.NewValue);
}
});
public static readonly DependencyProperty GroupNameOutProperty =
DependencyProperty.Register("GroupNameOut", typeof(string), typeof(MyNestedListBox), new UIPropertyMetadata(null));
}
ViewModel bound to the nested ListBox:
public class NestedItemsViewModel : ViewModelBase
{
private string _groupName;
public ObservableCollection<NestedItem> NestedItems { get; set; }
public string GroupName
{
get
{
return _groupName;
}
set
{
_groupName = value;
OnPropertyChanged(() => GroupName);
}
}
public NestedItemsViewModel()
{
NestedItems = new ObservableCollection<NestedItem>();
}
}
In my WPF application I am using the MVVM pattern. My view has a treeview which I bind an observableCollection of objects as defined below. What I want to do is to change the colour of a tree item name when the bound object sets it’s dirty property to true. I can get it to set the colour when I first populate the tree but then it doesn’t reflect the changes when the property changes between false and true.
public class HierarchicalItem
{
private readonly ObservableCollection<HierarchicalItem> _children = new ObservableCollection<HierarchicalItem>();
public ViewModelBase ViewModel { get; set; }
public string Name
{
get { return ViewModel.ViewModelName; }
}
public ICollection<HierarchicalItem> Children
{
get { return _children; }
}
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
if (_isSelected)
EventSystem.Publish(new SelectedViewModelMessage { SelectedViewModel = ViewModel });
}
}
public bool IsDirty
{
get { return ViewModel.IsDirty; }
}
}
This is the treeview xaml:
<TreeView Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Path=Views}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="True"/>
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=OneWayToSource}" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:HierarchicalItem}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDirty}" Value="True">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Here is the collection that gets bound to the tree:
private readonly ObservableCollection<HierarchicalItem> _views = new ObservableCollection<HierarchicalItem>();
public ObservableCollection<HierarchicalItem> Views
{
get { return _views; }
}
The ViewModels that are referenced in the HierarchicalItem collection all derive from a base class that exposes the “IsDirty” property. This is definantly changing state so I’m not sure if I’ve made a coding mistake or if what I want to achieve can’t be done this way. The classes all use the “INotifyPropertyChanged” interface. Here is the “IsDirty” property in from the ViewModel base class:
public class ViewModelBase : ValidatableModel
{
#region Properties
private bool _isDirty;
public bool IsDirty
{
get { return _isDirty; }
protected set
{
_isDirty = value;
OnPropertyChanged("IsDirty");
}
}
.
.
.
Etc
It's because your HierarchicalItem (the one you are having issues with) does not use a full INPC approach for its IsDirty property. The viewmodel does, but that is not enough, as the DataTemplate will be using the IsDirty property of the HierarchicalItem, so that needs to be full INPC property too
Changed that to this and it should be ok.
private bool _isDirty;
public bool IsDirty
{
get { return _isDirty; }
protected set
{
_isDirty = value;
OnPropertyChanged("IsDirty");
}
}
Though for your use case you will need to figure out some way to fire that. Or another thing you could try would be to change the binding in HierarchicalItem DataTemplate to this
<DataTrigger Binding="{Binding ViewModel.IsDirty}" Value="True">
Please let me know if I am doing something wrong in my code. I am trying to bind a WPF menu to a "MenuViewModel". The binding works as I expect in a non styled Window.
I am using MahApps.Metro for styling purposes only and this is how it looks after binding.
Here's the link to the source code http://sdrv.ms/W5uJpY
ViewModel:
public class Menu : INotifyPropertyChanged
{
public Menu()
{
IsEnabled = true;
Children = new List<Menu>();
}
#region [ Menu Properties ]
private bool _isEnabled;
private string _menuText;
private ICommand _command;
private IList<Menu> _children;
public string MenuText
{
get { return _menuText; }
set
{
_menuText = value;
RaisePropertyChanged("MenuText");
}
}
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
RaisePropertyChanged("IsEnabled");
}
}
public ICommand Command
{
get { return _command; }
set
{
_command = value;
RaisePropertyChanged("Command");
}
}
public IList<Menu> Children
{
get { return _children; }
set
{
_children = value;
}
}
#endregion
#region [INotifyPropertyChanged]
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
XAML:
<Menu Grid.Row ="0" IsMainMenu="True" x:Name="mainMenu" VerticalAlignment="Top" ItemsSource="{Binding Children}">
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
<!--Or can be the line below, both yield the same result-->
<!--<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MetroMenuItem}">-->
<!--NOTICE THAT SUB MENU's of OPEN work fine-->
<Setter Property="Header" Value="{Binding Path=MenuText}"/>
<Setter Property="Command" Value="{Binding Path=Command}"/>
<Setter Property="ItemsSource" Value="{Binding Path=Children}"/>
</Style>
</Menu.ItemContainerStyle>
</Menu>
I think I found an answer here
http://karlshifflett.wordpress.com/2008/02/03/wpf-sample-series-databound-hierarchicaldatatemplate-menu-sample/
It does the binding correctly - along with maintaining Separators.
I've created a WPF UserControl which contains a Button and a ComboBox. I'd like to change the style of both, depending on the position of the mouse, so the UIElement with the mouse over is coloured Black and the other is coloured Red. If neither are styled then the default styling will apply.
Don't worry, this nightmarish colour scheme is just to illustrate the concept!
Thanks in advance for your help.
XAML
<UserControl x:Class="WpfUserControlSample.ToolbarButtonCombo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfUserControlSample"
x:Name="Control"
mc:Ignorable="d"
d:DesignHeight="30">
<UserControl.Resources>
<Style TargetType="{x:Type local:ToolbarButtonCombo}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsButtonMouseOver}" Value="True">
<Setter Property="ButtonStyle" Value="Black"/>
<Setter Property="ComboStyle" Value="Red"/>
</DataTrigger>
<!--
<DataTrigger Binding="{Binding IsComboMouseOver}" Value="True">
<Setter Property="ButtonStyle" Value="Red"/>
<Setter Property="ComboStyle" Value="Black"/>
</DataTrigger>
-->
</Style.Triggers>
</Style>
</UserControl.Resources>
<StackPanel Orientation="Horizontal" Height="30">
<Button Name="btn" Background="{Binding ButtonStyle,ElementName=Control,Mode=OneWay}">
Test
</Button>
<ComboBox Name="cmb" Background="{Binding ComboStyle,ElementName=Control,Mode=OneWay}"></ComboBox>
</StackPanel>
</UserControl>
Codebehind:
namespace WpfUserControlSample
{
public partial class ToolbarButtonCombo : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public ToolbarButtonCombo()
{
InitializeComponent();
btn.MouseEnter += new MouseEventHandler(btn_MouseChanged);
btn.MouseLeave += new MouseEventHandler(btn_MouseChanged);
}
void btn_MouseChanged(object sender, MouseEventArgs e)
{
OnPropertyChanged("IsButtonMouseOver");
}
public bool IsButtonMouseOver
{
get { return btn.IsMouseOver; }
}
public static readonly DependencyProperty IsButtonMouseOverProperty =
DependencyProperty.Register("IsButtonMouseOver", typeof(string), typeof(ToolbarButtonCombo), new PropertyMetadata("false"));
public string ButtonStyle { get; set; }
public static readonly DependencyProperty ButtonStyleProperty =
DependencyProperty.Register("ButtonStyle", typeof(string), typeof(ToolbarButtonCombo));
public string ComboStyle { get; set; }
public static readonly DependencyProperty ComboStyleProperty =
DependencyProperty.Register("ComboStyle", typeof(string), typeof(ToolbarButtonCombo));
}
}
There are a two problems.
First your DataTrigger bindings do not look correct. They are looking for the IsButtonMouseOver on the DataContext, not the associated control. You'd need to use:
<DataTrigger Binding="{Binding IsButtonMouseOver, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="ButtonStyle" Value="Black"/>
<Setter Property="ComboStyle" Value="Red"/>
</DataTrigger>
Or:
<Trigger Property="IsButtonMouseOver" Value="True">
<Setter Property="ButtonStyle" Value="Black"/>
<Setter Property="ComboStyle" Value="Red"/>
</Trigger>
The other is your IsButtonMouseOver is not implemented correctly. You should do something like:
public static readonly DependencyProperty IsButtonMouseOverProperty = DependencyProperty.Register("IsButtonMouseOver",
typeof(bool), typeof(ToolbarButtonCombo), new PropertyMetadata(false));
public bool IsButtonMouseOver
{
get { return (bool)this.GetValue(IsButtonMouseOverProperty); }
set { this.SetValue(IsButtonMouseOverProperty, value); }
}
void btn_MouseChanged(object sender, MouseEventArgs e)
{
this.IsButtonMouseOver = this.btn.IsMouseOver;
}
Or even more correctly, make the IsButtonMouseOver a read-only dependency property like so:
private static readonly DependencyPropertyKey IsButtonMouseOverPropertyKey = DependencyProperty.RegisterReadOnly("IsButtonMouseOver",
typeof(bool), typeof(ToolbarButtonCombo), new FrameworkPropertyMetadata(false));
public static readonly DependencyProperty IsButtonMouseOverProperty = ToolbarButtonCombo.IsButtonMouseOverPropertyKey.DependencyProperty;
public bool IsButtonMouseOver {
get { return (bool)this.GetValue(IsButtonMouseOverProperty); }
private set { this.SetValue(IsButtonMouseOverPropertyKey, value); }
}
Your other properties (ButtonStyle and ComboStyle) would need to be properly implemented also, and their get/set methods are not backed by the dependency property.