In a .NET regex flavor, you may use lookbehinds like this:
Match foo not immediately preceded with bar
(?<!bar)foo
See the regex demo.
Match foo not preceded with bar anywhere in the string
(?s)(?<!bar.*?)foo
See the regex demo.
Match foo immediately preceded with bar
(?<=bar)foo
See the regex demo.
Match foo preceded with bar anywhere in the string
(?s)(?<=bar.*?)foo
See the regex demo.
The latter contains .*? in the negative lookbehind allowing the regex engine to check for bar and any zero or more chars immediately to the left of foo, so the bar does not have to come immediately before foo.
The (?s) inline modifier allows . to match any characters including newlines.
The current problem is easily solved by using a negative lookbehind (see the top scenario),
var result = Regex.Replace("XBB", "(?<!A)B", "AB");