WPF에서 또 다른 문제가 발생했습니다.일반 데이터 바인딩은 트리거를 사용하지 않는 것으로 보입니다.
나는 사용자 정의 컨트롤 모음을 가지고 있습니다 (복합 요소, 그리드 안의 테두리로 만들어진 것 등).
나는 바인딩과 함께 트리거를 통해 그들의 Background
색상을 제어하고 있습니다. 마우스 오버시 (트리거 및 사용자 정의 IValueConverter
에 의해 달성 됨) 조금 어두워지기를 원할뿐만 아니라 선택 (클릭) 할 때 색상을 변경하기를 원합니다. 후자는 일반 Setter
입니다.
<Grid Width="150" Height="50" Margin="5">
<Border CornerRadius="3" BorderBrush="Black" BorderThickness="0.5" >
<Border.Resources>
<local:BackgroundConverter x:Key="ColorConverter"/>
</Border.Resources>
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<Trigger Property="Grid.IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding Path=MyStatus, Converter={StaticResource ColorConverter}}"/>
</Trigger>
<Trigger Property="Grid.IsMouseOver" Value="False">
<Setter Property="Background" Value="{Binding Path=MyStatus, Converter={StaticResource ColorConverter}}"/>
</Trigger>
</Style.Triggers>
<Setter Property="Background" Value="{Binding Path=MyStatus, Converter={StaticResource ColorConverter}}"/>
</Style>
</Border.Style>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.6*"/>
<RowDefinition Height="0.5*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" FontSize="14" TextAlignment="Center" VerticalAlignment="Center" FontWeight="Bold">
<Label Foreground="{Binding Path=TextColor}" Content="{Binding Path=ID}"/>
</TextBlock>
<TextBlock Grid.Row="1" FontSize="9" TextAlignment="Center" VerticalAlignment="Top" Margin="0" Padding="0">
<Label Content="{Binding Path=StockName}"/>
</TextBlock>
</Grid>
</Border>
</Grid>
마우스 오버 효과는 컨트롤 중 하나를 클릭 할 때까지 올바르게 작동합니다. 트리거는 클릭하지 않은 컨트롤을 제외하고 해당 지점에서 작업을 중지합니다.
나는 약간 당황 스럽다. 트리거를 비활성화하지 않고 바인딩을 사용하려면 어떻게해야합니까?
필요한 경우 자세한 내용을 제공해 드리겠습니다.
@Rachel는
당신은 나중에 당신의 변환 코드를 게시 할 수 있습니까? IsMouseOver 속성이 변환기로 전달되는 방식을 볼 수 없으므로, 아마 변경 될 때 업데이트되지 않는 정적 값입니다. 그리고 이후 값이 트리거 될 때 값이 변경되지 않으므로 값을 재평가 할 필요가 없습니다. 당신은 IsMouseOver 및 MyStatus을 IMutliValueConverter를 사용하고 그것을 전달하는 더 좋을 수도, 그래서 어느 두 값이
변경의 나는 IMultiValueConverter
을 사용하지 않은 언제 다시 평가됩니다. 그 목적을 위해 나는 IsMouseOver
을 포함하는 내 자신의 "복합"객체를 만들었습니다. 이것은 배경색이 내 데이터 (항목이 선택되었거나 매핑되었는지 여부)와 마우스 오버 (배경색이 무엇이든 마우스 위로 약간 어둡게 표시됨)에서 계산되기 때문에 필요합니다. .
변환기 코드 :
public class BackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Debug.WriteLine("BackgroundConverter.Convert()");
if (!(value is StockViewBackgroundStatus))
{
throw new ArgumentException("value");
}
var casted = (StockViewBackgroundStatus)value;
if (casted.IsNone)
{
if (casted.IsMouseOver)
{
return new SolidColorBrush(Colors.Gray);
}
else
{
return CreateLinearGradient(Colors.Gray, false);
}
}
switch (casted.Status)
{
case StockItem.Status.Mapped:
{
return CreateLinearGradient(Color.FromRgb(83, 165, 18), casted.IsMouseOver);
}
case StockItem.Status.MappedElsewhere:
{
return CreateLinearGradient(Color.FromRgb(104, 189, 36), casted.IsMouseOver);
}
case StockItem.Status.NotMapped:
{
return CreateLinearGradient(Colors.LightGray, casted.IsMouseOver);
}
default:
{
throw new NotImplementedException(casted.Status.ToString());
}
}
}
private static LinearGradientBrush CreateLinearGradient(Color initial, bool darker)
{
var darkened = darker ? 0.1 : 0;
return new LinearGradientBrush(
Lighten(initial, 1.05 - darkened),
Lighten(initial, 0.95 - darkened),
90);
}
private static Color Lighten(Color initial, double factor)
{
Func<double, double> trunc = (value) => (Math.Max(0, Math.Min(255, value)));
var resulting = Color.FromRgb(
System.Convert.ToByte(trunc(initial.R * factor)),
System.Convert.ToByte(trunc(initial.G * factor)),
System.Convert.ToByte(trunc(initial.B * factor)));
return resulting;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Debug.WriteLine("BackgroundConverter.ConvertBack()");
return value;
}
}
StockItem
객체
public partial class StockItem : UserControl, INotifyPropertyChanged
{
private bool _empty;
public StockItem()
{
InitializeComponent();
DataContext = this;
}
private string _id;
public string ID
{
get
{
return _id;
}
set
{
_id = value;
RaisePropertyChanged("ID");
}
}
public Brush TextColor
{
get
{
Color color = IsSelected ? Colors.White : Colors.Black;
return new SolidColorBrush(color);
}
}
private string _stockName;
public string StockName
{
get
{
return _stockName;
}
set
{
_stockName = value;
RaisePropertyChanged("StockName");
}
}
StockViewBackgroundStatus _status;
public StockViewBackgroundStatus MyStatus
{
get
{
return new StockViewBackgroundStatus()
{
IsMouseOver = this.IsMouseOver,
IsNone = IsEmpty,
Status = MappingStatus
};
}
set
{
_status = value;
Debug.WriteLine("in " + ID + "...");
Debug.WriteLine("RaisePropertyChanged(\"IsMouseOver\")");
Debug.WriteLine("RaisePropertyChanged(\"MyStatus\")");
RaisePropertyChanged("IsMouseOver"); // added, but doesn't help
RaisePropertyChanged("MyStatus");
}
}
public bool IsEmpty
{
get
{
return _empty;
}
}
public static StockItem EmptyStock
{
get
{
return new StockItem()
{
_empty = true,
ID = "none",
Name = String.Empty
};
}
}
internal EventHandler Selected
{
get;
set;
}
private Status _mappingStatus;
public Status MappingStatus
{
get
{
return _mappingStatus;
}
set
{
_mappingStatus = value;
Debug.WriteLine("in " + ID + "...");
Debug.WriteLine("RaisePropertyChanged(\"MappingStatus\")");
Debug.WriteLine("RaisePropertyChanged(\"TextColor\")");
RaisePropertyChanged("MappingStatus");
RaisePropertyChanged("TextColor");
MyStatus = new StockViewBackgroundStatus() { IsMouseOver = this.IsMouseOver, IsNone = _empty, Status = value };
if (value == Status.Mapped && Selected != null)
{
Selected(this, null);
}
}
}
public bool IsSelected
{
get
{
return MappingStatus == Status.Mapped;
}
}
public enum Status
{
Mapped,
MappedElsewhere,
NotMapped
}
protected void RaisePropertyChanged(string property)
{
if (PropertyChanged == null)
{
return;
}
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
}
뷰 클래스 컬렉션
(I 실제로DataContext
로 설정하고있어 하나) 캡슐화
public class TargetStocks
{
public ObservableCollection<StockItem> AllStocks
{
get;
set;
}
public void Add(StockItem sv, EventHandler selected)
{
if (sv == null)
{
throw new ArgumentNullException("sv");
}
sv.MouseDown += sv_MouseDown;
if (selected != null)
{
sv.Selected += selected;
}
if (AllStocks == null)
{
AllStocks = new ObservableCollection<StockItem>();
}
AllStocks.Add(sv);
}
public void AddRange(IEnumerable<StockItem> stocks, EventHandler selected)
{
foreach (var stock in stocks)
{
Add(stock, selected);
}
}
void sv_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (!(sender is StockItem))
{
return;
}
var sv = (StockItem)sender;
foreach (StockItem stock in AllStocks)
{
if (stock.MappingStatus == StockItem.Status.Mapped)
{
// this seems to kill the trigger
stock.MappingStatus = StockItem.Status.NotMapped;
}
if (stock == sv && sv.MappingStatus != StockItem.Status.Mapped)
{
// as above
stock.MappingStatus = StockItem.Status.Mapped;
}
}
}
}
디버깅에 표시된 것처럼 재고 항목을 클릭하기 전에 (또는 그 중 하나의 MappingStatus
이 변경되기 전에) 마우스 오버 효과는 변환기를 전혀 트리거하지 않고 작동합니다.
Convert
이 전혀 호출되지 않았습니다.
MouseDown
이벤트 핸들러에 MappingStatus
을 설정하여 트리거를 비활성화 (또는 분리)하는 것 같습니다.
배경색을 변경하는 클릭 코드를 포함하도록 질문을 편집 할 수 있습니까? 또한, 당신의'Click' 이벤트가 바인딩의 소스 속성이나 테두리의'Background' 속성을 설정합니까? 두 번째 경우 [Depecencey Property Precedence] (http://msdn.microsoft.com/en-us/library/ms743230.aspx)는 개체 자체에 설정된 값이 스타일 또는 트리거 된 값보다 우선하도록 지정합니다. – Rachel
@Rachel이 묻습니다 - 당신의'Click '은 무엇을하고 있습니까? – XAMeLi
어쩌면 내가 누락되었지만 트리거가 모두 동일한 값을 반환하지 않습니까? 그들은'Status'를'Binding Path = MyStatus, Converter = {StaticResource ColorConverter}} '로 설정합니다.이 값은 기본 Setter와 같은 값이기 때문에 배경색은 마우스가 닫혔는지에 관계없이 정적으로 유지됩니다 그것 또는 아닙니다 ... – Rachel