Binding to List element when element number changes - wpf

private List<Report> _reports = new List<Report>();
public Report CurrentReport
{
get { return _reports[_componentIterator]; }
set { _reports[_componentIterator] = value; }
}
I have a _reports field and it's a list of Report objects.
I use a CurrentReport property to access current Report object based on _componentIterator.
How do I bind to some of Report properties so that changing _componentIterator won't break my binding?
If I bind like this, every _componentIterator change breaks binding.
Binding designatorTextBlockBinding = new Binding(nameof(CurrentReport.Designator));
designatorTextBlockBinding.Source = CurrentReport;
_artifactControl.DesignatorTextBlock.SetBinding(Controls.TextBlock.TextProperty, designatorTextBlockBinding);

Declare the Binding like shown below, and make sure the CurrentReport property fires a change notification.
var designatorTextBlockBinding = new Binding
{
Path = new PropertyPath("CurrentReport.Designator"),
Source = this
};
or
var designatorTextBlockBinding = new Binding
{
Path = new PropertyPath(
nameof(CurrentReport) + "." + nameof(CurrentReport.Designator)),
Source = this
};
or
var designatorTextBlockBinding = new Binding(
nameof(CurrentReport) + "." + nameof(CurrentReport.Designator))
{
Source = this
};

Related

CoerceValueCallback not called after ClearValue

I have a CheckBox which I have extended to add a IsReadOnly property. The property has a Coerce callback, which will look up access rights for the current user, and return true, if the user does not have permissions:
private static object CoerceIsReadOnly(DependencyObject d, object baseValue)
{
var owner = (CheckBox)d;
bool isReadOnly = (bool)baseValue;
if (isReadOnly == false)
{
if (AccessControl.HasFullAccess(owner) == false)
{
return true; // If we do not have access, and read only is false, we coerce it to true
}
}
return baseValue;
}
Now I did some experiments to look at the different values:
XAML
<vc:CheckBox Content="AccessControl" x:Name="ChkBoxAccessControl" Margin="5" vc:AccessControl.OverrideAccessRights="NoAccess"/>
Code-behind
var defaultValue = CheckBox.IsReadOnlyProperty.GetMetadata(typeof(CheckBox)).DefaultValue; // False
var localValue = ChkBoxAccessControl.ReadLocalValue(CheckBox.IsReadOnlyProperty); // Unset (we didn't set a value in code or XAML)
var actualValue = ChkBoxAccessControl.GetValue(CheckBox.IsReadOnlyProperty); // True (coerced)
ChkBoxAccessControl.SetValue(CheckBox.IsReadOnlyProperty, false);
var localValue2 = ChkBoxAccessControl.ReadLocalValue(CheckBox.IsReadOnlyProperty); // False
var actualValue2 = ChkBoxAccessControl.GetValue(CheckBox.IsReadOnlyProperty); // True
ChkBoxAccessControl.ClearValue(CheckBox.IsReadOnlyProperty);
var localValue3 = ChkBoxAccessControl.ReadLocalValue(CheckBox.IsReadOnlyProperty); // Unser
var actualValue3 = ChkBoxAccessControl.GetValue(CheckBox.IsReadOnlyProperty); // false??? WTH...
So to my surprise, the last actualValue3 returns false.
Apparently when calling ClearValue, it does not call the coerce callback. Is this to be expected? Can anyone explain why this would be correct?
Is this to be expected?
Yes, see this answer. When you clear the value, you get the default non-coerced one.
Also, actualValue isn't coerced in your example but actualValue2 is.
A dependency property stores and remembers the non-coerced value. You can read more about this here.

How to add an item to a custom index in Sitecore programmatically?

I have created my custom Index in Sitecore with FlatDataCrawler.
Now I am going to add new item inherited from AbstractIndexable to my index.
private void Test() {
var newItem = new ContactIndexable {
Number = new System.Random().Next(500, 10000),
MyField = "Item from IMPORTER"
};
var index = ContentSearchManager.GetIndex("my_index");
using (var ctx = index.CreateUpdateContext()) {
//This line doesn't work:
ctx.Index.Operations.Add(newItem, index.CreateUpdateContext(), index.Configuration);
index.Refresh(newItem);
}
}
Calling this code causes that only the GetItemsToIndex method is called in my custom crawler, but the element is not added to the Index.
So, how can I add a new item to my custom index from code?
This method works correctly and a new element is added to the index:
protected override IEnumerable<ContactIndexable> GetItemsToIndex() {
List<ContactIndexable> items = new List<ContactIndexable>() {
new ContactIndexable()
{
MyField = "Created in crawler"
}
};
return items;
}
You're really close. You have to queue up the context first and then add and commit.
using (var solr = ContentSearchManager.GetIndex("my_index'))
{
var ctx = solr.CreateUpdateContext();
solr.Operations.Add(newItem, ctx, solr.Configuration);
ctx.Commit();
}
Since this is using SolrNet under the hood, all operations against Solr have to be committed.

Anotar.Serilog and logging

I premit that I'm quite new to Anotar / Serilog, I've my WPF application that uses the Repository Pattern and I've the repo strucured as
public class CalendarRepository : DefaultRepositoryBase, ICalendarRepository
{
public Task<IList<CalendarTemplate>> GetCalendarTemplatesAsync(int? template)
{
JsonServiceClient client = GetServiceStackClient();
var request = new CalendarTemplatesRequest
{
Template = template
};
return client.PostAsync(request);
}
public Task<IList<Currency>> GetCurrenciesAsync(int? currency)
{
JsonServiceClient client = GetServiceStackClient();
var request = new CurrenciesRequest
{
Currency = currency
};
return client.PostAsync(request);
}
public Task<IList<CurrencyCalendar>> GetCurrencyCalendarsAsync(IEnumerable<int> currencies)
{
JsonServiceClient client = GetServiceStackClient();
var request = new CurrencyCalendarsRequest
{
Currencies = currencies
};
return client.PostAsync(request);
}
Right now I was logging in the viewmodels as
LogTo.Information("Getting calendar currencies {SelectedCurrencies}",selectedCurrenciesId.Select(x=>x.Id));
var items = await repository.GetCurrencyCalendarsAsync(selectedCurrenciesId.Select(x => x.Id));
I was wondering if there's an Attribute that I can apply to a class in order to automatically log the Method and the parameters.
Right now my logged is configured as
var log =
new LoggerConfiguration().MinimumLevel.ControlledBy(
levelSwitch: new LoggingLevelSwitch(LogEventLevel.Debug)).WriteTo.File(#".\logs\serilog.log",outputTemplate: "{Timestamp: yyyy-MM-dd HH:mm:ss.fff} [{Level}] [{SourceContext}] {Message}{NewLine}{Exception}").CreateLogger();
Serilog.Log.Logger = log;
Thanks
You can get the method name and line number by adding {Method} and {LineNumber} to the output template respectively.
As far as I know, there is no way to automatically log the parameters; you would need to do this manually.

Save a value to Database - MVC

I am trying to save a value in the "UserController" but I cannot seem tog et it to save to the database.
I can get the database value as stored in the UserController to change so that when the value is submitted and the view is refreshed it looks as though it was stored. (ie. changing from test to tested) However, as soon as I refresh the page again it returns to the previous value and the database shows no change throughout this.
UserController:
var g = httpPost.VanityUrl;
DB.ppUser_editUser(g);
ppUser_editUser in ppUser:
public ppUser ppUser_editUser(string personVanity)
{
ppUser user = SessionUser.LoggedInUser.Person;
user.VanityUrl = personVanity;
BaseDB.SubmitChanges();
return user;
}
EditProfile View:
<div>
#Html.LabelFor(m => m.VanityUrl, "Edit your Custom Url:")
#Html.TextBoxFor(m => m.VanityUrl, new { maxlength = 15 })
</div>
BaseDB:
public partial class StudioKit_MVC3Repository : IDisposable
{
private StudioKit_MVC3ModelsDataContext _BaseDB;
public StudioKit_MVC3ModelsDataContext BaseDB
{
get
{
if (_BaseDB == null)
{
if (StudioKit_MVC3Config.EnvironmentDetail.Name == "Production")
{
_BaseDB = new StudioKit_MVC3ModelsDataContext(StudioKit_MVC3Config.EnvironmentDetail.ConnectionString);
}
else
{
var sqlConnection = new SqlConnection(StudioKit_MVC3Config.EnvironmentDetail.ConnectionString);
var conn = new ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
_BaseDB = new StudioKit_MVC3ModelsDataContext(conn);
}
}
return _BaseDB;
}
}
}
Edit:
I figured out the problem. I was saving the value to the session user instance and not the actual database. I got rid of the method and in the controller I simply put:
ppUser check = DB.ppUser_GetUserByPersonID(model.cskPersonID);
check.VanityUrl = httpPost.VanityUrl;
DB.Save();

How can I delete a hyperlink in a Silverlight RichTextBox?

I have a RichTextBox that the user can edit to create a hyperlink (in my case to another page with the document rather than an external URL). Having successfully created the link I now need to be able to remove it.
I have code that identifies that I've got a hyperlink in the current selection:
TextSelection linkText = richTextBox.Selection;
if (linkText != null && !string.IsNullOrWhiteSpace(linkText.Text))
{
XElement root = XElement.Parse(linkText.Xaml);
XNamespace ns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
XElement linkElement = root.Element(ns + "Paragraph").Element(ns + "Hyperlink");
if (linkElement != null)
{
// Get here if have a Hyperlink. How do I remove or update?
}
}
However, I'm now stuck on the bit that goes inside the if test. How do I find the hyperlink so I can remove it completely?
My code for setting up the hyperlink is:
TextSelection linkText = richTextBox.Selection;
var hyperlink = new Hyperlink();
hyperlink.Inlines.Add(linkText.Text);
if (!String.IsNullOrEmpty(selectedTopic)) // A string holding the link target
{
// Setup hyperlink here
}
linkText.Insert(hyperlink);
I've managed to work out how to update the hyperlink:
foreach (var block in richTextBox.Blocks)
{
Paragraph p = block as Paragraph;
foreach (var inline in p.Inlines)
{
var hyperlink = inline as Hyperlink;
if (hyperlink != null && hyperlink.NavigateUri.AbsoluteUri.Contains(currentLink))
{
hyperlink.NavigateUri = new Uri(newLink);
}
}
}
I could use the same approach to delete the hyperlink, but how do I convert the Hyperlink to a normal Inline?
Looks like you are getting close you just need to hold a reference to the link then use Remove. Something like the following (I like to use Linq to make things a little more succinct):-
foreach (var p in richTextBox.Blocks.OfType<Paragraph>())
{
var hyperlink = p.Inlines.OfType<HyperLink>()
.FirstOrDefault(hl => hl.NavigateUri.AbsoluteUri.Contains(currentLink));
if (hyperlink != null)
{
p.Inlines.Remove(hyperlink);
break;
}
}
Edit: Want to leave the content of hyperlink in place? (i.e., just remove the wrapping hyperlink),
foreach (var p in richTextBox.Blocks.OfType<Paragraph>())
{
var hyperlink = p.Inlines.OfType<HyperLink>()
.FirstOrDefault(hl => hl.NavigateUri.AbsoluteUri.Contains(currentLink));
if (hyperlink != null)
{
int index = p.Inlines.IndexOf(hyperlink);
Span span = new Span();
foreach (var inline in hyperlink.Inlines.ToArray())
{
hyperlink.Inlines.Remove(inline);
span.Inlines.Add(inline);
}
// You may need code here to preserve the Font properties etc from hyperlink to span.
p.Inlines[index] = span;
break;
}
}

Resources