/ / Comment forcer une actualisation de la liaison lorsqu'elle est liée à l'objet entier dans un modèle - wpf, wpfdatagrid

Comment forcer une actualisation de la liaison lorsqu'elle est liée à l'objet entier dans un modèle - wpf, wpfdatagrid

J'ai une liste de classes "Rule" qui est la source d'un DataGrid. Dans cet exemple, j'ai l'une des colonnes qui est un DataGridTemplateColumn qui est lié à la propriété de dépendance "Vérifié".

Le problème que j'ai, c'est que j'ai unVerifyColorConverter où je souhaite passer dans l'objet "Rule" ENTIER de la ligne sélectionnée afin que je puisse examiner l'instance de Rule et retourner un pinceau approprié. Je le fais lors du réglage de l'arrière-plan de la bordure (voir le code ci-dessous - Background = "{Binding Converter = {StaticResource convVerify}}")

<DataGridTemplateColumn Header="Verified" Width="150">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border Background="{Binding Converter={StaticResource convVerify}}"
CornerRadius="4" Height="17" Margin="2,0,2,0" VerticalAlignment="Center" >
<Grid>
<TextBlock Foreground="Yellow" Text="{Binding Path=Verified, Mode=OneWay}" TextAlignment="Center" VerticalAlignment="Center"
FontSize="11" FontWeight="Bold" />
</Grid>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>

Tout fonctionne bien lorsque je règle la source sur leDataGrid mais lorsque l'objet "Rule" sous-jacent est modifié, le convertisseur n'est pas appelé de sorte que le pinceau reste le même. Comment puis-je forcer la mise à jour lorsque je modifie certaines des propriétés de l'instance "Rule"?

Toute aide appréciée!

Le convertisseur ressemble approximativement à ceci:

    [ValueConversion(typeof(CRule), typeof(SolidColorBrush))]
public class VerifyColorConverter : IValueConverter
{
#region IValueConverter Members

public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
CRule rule = value as CRule;

Color clr = Colors.Red;

int count = 0;
int verified = 0;

if (rule != null)
{
count = rule.TotalCount;
verified = rule.NoOfVerified;
}

if (count == 0) clr = Colors.Transparent;
else if (verified == 0) clr = (Color)ColorConverter.ConvertFromString("#FFD12626");
else if (verified < count) clr = (Color)ColorConverter.ConvertFromString("#FF905132");
else clr = (Color)ColorConverter.ConvertFromString("#FF568D3F");

SolidColorBrush brush = new SolidColorBrush(clr);
return brush;
}

public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}

#endregion
}

MODIFIER

Cela fait partie de la classe Rule:

   /// <summary>
/// Compliance Restriction (Rule)
/// </summary>
public class Rule : BindElement
{
public CMode Mode { get; private set; }
public int RuleID { get; private set; }
public string RuleDescription { get; private set; }

private int _NoOfVerified = 0;
private int _TotalCount = 0;

public int NoOfVerified
{
get { return _NoOfVerified; }
set { _NoOfVerified = value; RaiseChanged("Progress"); RaiseChanged("Verified"); }
}

public int TotalCount
{
get { return _TotalCount; }
set { _TotalCount = value; RaiseChanged("Progress"); RaiseChanged("Verified"); }
}

public string Verified
{
get
{
if (TotalCount == 0) return "Nothing to verify";
return string.Format("Verified {0} out of {1}", NoOfVerified, TotalCount);
}
}

Réponses:

0 pour la réponse № 1

Vous pouvez essayer d'utiliser un MultiValueConverter au lieu d'un habitué Converteret transmettez-lui les propriétés de règle dont vous avez besoin, ou vous pouvez augmenter un CollectionChanged événement lorsqu'une propriété de la règle est modifiée. Je préfère généralement ne pas le faire car je ne sais pas comment cela affecte les performances, mais c'est une option.

Utiliser un MultiConverter

public object Convert(object[] values, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
Color clr = Colors.Red;

int count = 0;
int verified = 0;

if (values.Count >= 2
&& int.TryParse(count, values[0].ToString())
&& int.TryParse(verfieid, values[1].ToString()))
{
if (count == 0) clr = Colors.Transparent;
else if (verified == 0) clr = (Color)ColorConverter.ConvertFromString("#FFD12626");
else if (verified < count) clr = (Color)ColorConverter.ConvertFromString("#FF905132");
else clr = (Color)ColorConverter.ConvertFromString("#FF568D3F");
}

SolidColorBrush brush = new SolidColorBrush(clr);
return brush;
}

XAML pour MultiConverter:

<Border.Background>
<MultiBinding Converter="{StaticResource convVerify}">
<Binding Value="{Binding TotalCount}" />
<Binding Value="{Binding NoOfVerified}" />
</MultiBinding>
</Border.Background>

Utilisation des événements de modification de propriété

RulesCollection.CollectionChanged += RulesCollection_Changed;

void RulesCollection_Changed(object sender, CollectionChangedEventArgs e)
{
if (e.NewItems != null)
foreach(Rule rule in e.NewItems) // May need a cast here
rule.PropertyChanged += Rule_PropertyChanged;

if (e.OldItems != null)
foreach(Rule rule in e.OldItems) // May need a cast here
rule.PropertyChanged -= Rule_PropertyChanged;
}

void Rule_PropertyChanged()
{
RaisePropertyChanged("RulesCollection");
}

0 pour la réponse № 2

OK - j'ai trouvé un moyen de contourner cela - ce que j'ai faitexpose l'objet en tant que propriété, puis appelle OnPropertyChanged pour cette propriété chaque fois que quelque chose change. Ceci est correctement récupéré par l'objet Bind et remis au convertisseur chaque fois qu'une propriété change !!

    [Serializable()]
public class BindElement : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members

[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}

public void RaiseChanged(string s)
{
OnPropertyChanged(new PropertyChangedEventArgs(s));
}

#endregion
}

public class BindElement2 : BindElement
{
public void RaiseChanged(string s)
{
base.RaiseChanged(s);
NudgeMyself();
}

public void NudgeMyself()
{
base.RaiseChanged("Myself");
}
}

/// <summary>
/// Compliance Restriction (Rule)
/// </summary>
public class CRule : BindElement2
{
public CMode Mode { get; private set; }
public int RuleID { get; private set; }
public string RuleDescription { get; private set; }

private int _NoOfVerified = 0;
private int _TotalCount = 0;

public int NoOfVerified
{
get { return _NoOfVerified; }
set { _NoOfVerified = value; RaiseChanged("Progress"); RaiseChanged("Verified"); }
}

public int TotalCount
{
get { return _TotalCount; }
set { _TotalCount = value; RaiseChanged("Progress"); RaiseChanged("Verified"); }
}

public string Verified
{
get
{
if (TotalCount == 0) return "Nothing to verify";
return string.Format("Verified {0} out of {1}", NoOfVerified, TotalCount);
}
}

public CRule Myself
{
get { return this; }
}

et d'autres classes peuvent dériver de BindElement2 et faire de même: (créer une propriété Myself qui expose l'instance elle-même)

    public class CTradeRule : BindElement2
{
public CRule Rule { get; set; }
public bool IsLocked { get; set; }      // if true this should prevent a Reason from being given
public bool IsVerified { get { return Reason.Length > 0; } }

private string _Reason = "";        // ** no reason **
public string Reason
{
get { return _Reason; }
set { _Reason = value; RaiseChanged("Reason"); }
}

public int Progress
{
get { return (IsVerified ? 1 : 0); }
}

public override string ToString()
{
return string.Format("Rule: {0}, Reason: {1}", Rule.RuleID, _Reason);
}

public CTradeRule Myself
{
get { return this; }
}
}

Maintenant, dans le xaml, je peux le faire: (notez le chemin de liaison = moi-même) qui garantit ensuite que l'objet entier est envoyé au convertisseur QUAND les propriétés changent !!

<DataGridTemplateColumn Header="Verified" Width="150">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border Background="{Binding Path=Myself, Converter={StaticResource convVerify}}"
CornerRadius="4" Height="17" Margin="2,0,2,0" VerticalAlignment="Center" >
<Grid>
<TextBlock Foreground="Yellow" Text="{Binding Path=Verified, Mode=OneWay}" TextAlignment="Center" VerticalAlignment="Center"
FontSize="11" FontWeight="Bold" />
</Grid>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>