これは、初めてICommandをデータバインドしようとするときです。 Iデジタルは、私はボタンのように行動したいLED制御、私はLEDのように見えるように、ButtonコントロールのためのDataTemplateを変更しました:複数のボタンをクリックした後のICommandの「フリーズ」のWPFデータバインド
LED.xaml
<UserControl x:Class="LedControlDatabindingTest.LED"
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"
x:Name="root"
mc:Ignorable="d"
Height="Auto" Width="Auto">
<Grid DataContext="{Binding ElementName=root}">
<StackPanel Orientation="{Binding LEDOrientation, FallbackValue=Vertical}">
<!-- LED portion -->
<Button BorderBrush="Transparent" Background="Transparent" Click="Button_Click">
<Button.ContentTemplate>
<DataTemplate>
<Grid>
<Ellipse Grid.Column="0" Margin="3" Height="{Binding ElementName=root, Path=LEDSize, FallbackValue=16}"
Width="{Binding ElementName=root, Path=LEDSize, FallbackValue=16}"
Fill="{Binding ElementName=root, Path=LEDColor, FallbackValue=Green}"
StrokeThickness="2" Stroke="DarkGray" HorizontalAlignment="Center" />
<Ellipse Grid.Column="0" Margin="3" Height="{Binding ElementName=root, Path=LEDSize, FallbackValue=16}"
Width="{Binding ElementName=root, Path=LEDSize, FallbackValue=16}" HorizontalAlignment="Center">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.5,1.0">
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="1.5" ScaleY="1.5"/>
<TranslateTransform X="0.02" Y="0.3"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Offset="1" Color="#00000000"/>
<GradientStop Offset="0.4" Color="#FFFFFFFF"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
</Grid>
</DataTemplate>
</Button.ContentTemplate>
</Button>
<!-- label -->
<TextBlock Grid.Column="1" Margin="3" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding LEDLabel, FallbackValue=0}" />
</StackPanel>
</Grid>
</UserControl>
を私はホストアプリケーションが欲しいですLEDのサイズ、色、ラベルなどのプロパティにデータバインドすることができます。さらに、私はコマンドハンドラにバインドできるようにしたい。
LED.xaml.cs
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 LedControlDatabindingTest {
/// <summary>
/// Interaction logic for LED.xaml
/// </summary>
public partial class LED : UserControl
{
public static DependencyProperty LEDColorProperty = DependencyProperty.Register("LEDColor", typeof(Brush), typeof(LED));
public Brush LEDColor
{
get { return this.GetValue(LEDColorProperty) as Brush; }
set {
this.SetValue(LEDColorProperty, value);
}
}
public static DependencyProperty LEDSizeProperty = DependencyProperty.Register("LEDSize", typeof(int), typeof(LED));
public int LEDSize
{
get { return (int)GetValue(LEDSizeProperty); }
set {
SetValue(LEDSizeProperty, value);
}
}
public static DependencyProperty LEDLabelProperty = DependencyProperty.Register("LEDLabel", typeof(string), typeof(LED));
public string LEDLabel
{
get { return (string)GetValue(LEDLabelProperty); }
set {
SetValue(LEDLabelProperty, value);
}
}
public static DependencyProperty LEDOrientationProperty = DependencyProperty.Register("LEDOrientation", typeof(Orientation), typeof(LED));
public Orientation LEDOrientation
{
get { return (Orientation)GetValue(LEDOrientationProperty); }
set {
SetValue(LEDOrientationProperty, value);
}
}
public static readonly DependencyProperty LEDClickedProperty = DependencyProperty.Register("LEDClicked", typeof(ICommand), typeof(LED), new PropertyMetadata(null));
public ICommand LEDClicked
{
get { return (ICommand)GetValue(LEDClickedProperty); }
set { SetValue(LEDClickedProperty, value); }
}
public LED()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
LEDClicked.Execute(null);
}
}
}
私のテストアプリケーションは簡単です。
MainWindow.xaml:
<Window x:Class="LedControlDatabindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:LedControlDatabindingTest"
Title="MainWindow" Height="70" Width="250">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Digital Inputs:" />
<ListBox ItemsSource="{Binding AvailableDigitalInputs}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<local:LED LEDLabel="{Binding Index}" LEDColor="{Binding Color}" LEDSize="12" LEDClicked="{Binding Clicked}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</StackPanel>
</Window>
そこには-NOSは、自分のアプリケーションのためのDataContextのように、私のコードビハインドでそうではないが、私はこのデモの目的のために、それは今のところ大丈夫だと思います。
MainWindow.xaml.cs:私は、このアプリケーションを実行すると
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using System;
using System.Collections.Generic;
using System.ComponentModel;
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 LedControlDatabindingTest {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private class DigitalInputData : ViewModelBase
{
private Brush _color;
public Brush Color
{
get { return _color; }
set {
_color = value;
RaisePropertyChanged();
}
}
public int Index { get; set; }
public ICommand Clicked { get; set; }
private bool _state;
public DigitalInputData(int index, Brush on_color)
{
Index = index;
Color = Brushes.LightGray;
Clicked = new RelayCommand(() => {
// get current state of this digital input and then toggle it
_state = !_state;
// read back and update here until I get threaded updates implemented
Color = _state ? on_color : Brushes.LightGray;
});
}
}
private List<DigitalInputData> _inputs = new List<DigitalInputData>();
public ICollectionView AvailableDigitalInputs { get; set; }
public MainWindow()
{
InitializeComponent();
// For this example only, set DataContext in this way
DataContext = this;
for(int i=0; i<4; i++) {
_inputs.Add(new DigitalInputData(i, Brushes.Green));
}
AvailableDigitalInputs = CollectionViewSource.GetDefaultView(_inputs);
}
}
}
、すべてのものは、私のデータバインドされたプロパティに応じて適切にレンダリングします。クリックハンドラも同様に機能し、LEDの状態をトグルします。
しかし、LEDボタンを何回かクリックすると、ある時点(多分20回以上のクリック後)で、データバインドされたICommandの呼び出しが停止します。どうして?
あなたの 'LED'コントロールは' UserControl'から取り除かれ、 'DataTemplate'で使われることができます。なぜなら、UCはかなり高価だからです。とにかく 'DataTemplate'であなたが使用したいバインディングが利用可能になります。また、バインディング 'xmlns:diag =" clr-namespace:System.Diagnostics; assembly = WindowsBase "' thenLEDClicked = "{Binding Clicked、diag:PresentationTraceSources.TraceLevel = High}"に関する情報を取得しようとします。 – XAMlMAX
@ XAMlMAX私は、事実、PresentationTraceSourcesのネームスペースは実際には必要ではないことを知った。ちょうど 'PresentationTraceSources.TraceLevel = High'がうまく動作する。毎回ネームスペース属性のコピーを見つけるのに苦労します。 –
@XAMIMAX問題が解消されたかどうかを確認しようとします。なぜ私がここに提示した質問がとても悪くて-1になったのだろうかと思います。 – Dave